Kode Kesalahan 1117 Terlalu banyak kolom; Batas kolom pada tabel MySQL

37

Saya memiliki tabel dengan 1699 kolom dan ketika saya mencoba memasukkan lebih banyak kolom,

Kode Kesalahan: 1117. Terlalu banyak kolom

Dalam tabel ini saya hanya memiliki 1000 baris. Bagi saya yang paling penting adalah jumlah kolom. Apakah ada batasan di atas meja? Saya ingin membuat 2000 kolom. Apakah itu mungkin?

OHLÁLÁ
sumber
22
Tuan yang baik, untuk apa. Baunya seperti desain database yang sangat buruk. Atau mungkin Anda menggunakan alat yang salah untuk pekerjaan itu. Mungkin Anda harus melihat normalisasi basis data
Zoredache
12
Putar monitor Anda 90 derajat. Lebih serius lagi, MySQL (atau hampir semua RDBMS lainnya) tidak dirancang untuk banyak kolom.
11
Dan mengapa 2000 sensor mengarah ke 2000 kolom? Mendesain ulang basis data Anda. Buat tabel sensor terpisah atau semacamnya, tapi JANGAN tambahkan setiap sensor sebagai kolom baru. Hal yang sangat salah untuk dilakukan.
6
Nomor meja maksimum ... tunggu di sana! Anda mungkin hanya perlu beberapa tabel. Bahkan tidak mempertimbangkan membuat 2000 tabel, bukan 2000 kolom!
2
Tolong, Tolong, Tolong baca tentang Normalisasi Database !

Jawaban:

35

Mengapa Anda perlu membuat tabel dengan bahkan 20 kolom, apalagi 2000 ???

Memang, data yang dinormalisasi dapat mencegah keharusan melakukan GABUNG untuk mengambil banyak kolom data. Namun, jika Anda memiliki lebih dari 10 kolom, Anda harus berhenti dan memikirkan apa yang akan terjadi di bawah tenda selama pengambilan data.

Jika tabel kolom 2000 mengalami SELECT * FROM ... WHERE, Anda akan menghasilkan tabel temp besar selama pemrosesan, mengambil kolom yang tidak perlu, dan membuat banyak skenario di mana paket komunikasi ( max_allowed_packet ) akan didorong ke tepi jurang di setiap kueri.

Pada hari-hari awal saya sebagai pengembang, saya bekerja di sebuah perusahaan pada tahun 1995 di mana DB2 adalah RDBMS utama. Perusahaan memiliki satu tabel yang memiliki 270 kolom, lusinan indeks, dan memiliki masalah kinerja mengambil data. Mereka menghubungi IBM dan meminta konsultan memeriksa arsitektur sistem mereka, termasuk tabel monolitik yang satu ini. Perusahaan diberi tahu "Jika Anda tidak menormalkan tabel ini dalam 2 tahun ke depan, DB2 akan gagal pada kueri yang melakukan Pemrosesan Stage2 (setiap kueri yang membutuhkan pengurutan pada kolom yang tidak diindeks)." Ini diceritakan kepada perusahaan multi-triliun dolar, untuk menormalkan tabel 270 kolom. Terlebih lagi tabel kolom 2000.

Dalam hal mysql, Anda harus mengimbangi desain buruk seperti itu dengan menetapkan opsi yang sebanding dengan Pemrosesan DB2 Stage2. Dalam hal ini, opsi tersebut adalah

Tweeking pengaturan ini untuk menebus keberadaan lusinan, apalagi ratusan, kolom bekerja dengan baik jika Anda memiliki TB RAM.

Masalah ini berlipat ganda secara geometris jika Anda menggunakan InnoDB karena Anda harus berurusan dengan MVCC (Multiversion Concurrency Control) yang mencoba melindungi ton kolom dengan setiap SELECT, UPDATE, dan DELETE melalui isolasi transaksi.

KESIMPULAN

Tidak ada pengganti atau bantuan-band yang dapat menggantikan desain yang buruk. Tolong, demi kewarasan Anda di masa depan, normalkan meja itu hari ini !!!

RolandoMySQLDBA
sumber
1
Saya bisa membayangkan bagaimana perusahaan akan lakukan ketika diberitahu ini. Mereka menambahkan kait svn atau membuat "pedoman praktik terbaik DB" yang meminta pengembang untuk tidak mengurutkan kolom yang tidak diindeks dalam SQL. Sebagai gantinya, mereka melakukan pengurutan dalam aplikasi dengan menerapkan algoritma pengurutan data besar mereka sendiri.
Gqqnbig
25

Saya mengalami kesulitan membayangkan apa pun di mana model data secara sah dapat memuat 2000 kolom dalam tabel yang dinormalisasi dengan benar.

Dugaan saya adalah bahwa Anda mungkin melakukan semacam skema "isi kosong" skema dinormalisasi, di mana Anda sebenarnya menyimpan semua jenis data yang berbeda dalam satu tabel, dan bukannya memecah data ke dalam tabel terpisah dan membuat hubungan , Anda memiliki berbagai bidang yang merekam "tipe" data apa yang disimpan dalam baris tertentu, dan 90% bidang Anda NULL. Meski begitu, meskipun, ingin mencapai 2000 kolom ... ya.

Solusi untuk masalah Anda adalah memikirkan kembali model data Anda. Jika Anda menyimpan tumpukan besar data kunci / nilai yang terkait dengan catatan yang diberikan, mengapa tidak memodelkannya seperti itu? Sesuatu seperti:

CREATE TABLE master (
    id INT PRIMARY KEY AUTO_INCREMENT,
    <fields that really do relate to the
    master records on a 1-to-1 basis>
);

CREATE TABLE sensor_readings (
    id INT PRIMARY KEY AUTO_INCREMENT,
    master_id INT NOT NULL,   -- The id of the record in the
                              -- master table this field belongs to
    sensor_id INT NOT NULL,
    value VARCHAR(255)
);

CREATE TABLE sensors (
    id INT PRIMARY KEY AUTO_INCREMENT,
    <fields relating to sensors>
);

Kemudian untuk mendapatkan semua entri sensor yang terkait dengan catatan "master" yang diberikan, Anda bisa saja SELECT sensor_id,value FROM sensor_readings WHERE master_id=<some master ID>. Jika Anda perlu mendapatkan data untuk catatan di mastertabel bersama dengan semua data sensor untuk catatan itu, Anda bisa menggunakan gabungan:

SELECT master.*,sensor_readings.sensor_id,sensor_readings.value
FROM master INNER JOIN sensor_readings on master.id=sensor_readings.master_id
WHERE master.id=<some ID>

Dan kemudian bergabung lebih jauh jika Anda membutuhkan detail dari masing-masing sensor.

Womble
sumber
18

Ini adalah sistem pengukuran dengan 2000 sensor

Abaikan semua komentar yang berteriak tentang normalisasi - apa yang Anda minta bisa menjadi desain database yang masuk akal (di dunia yang ideal) dan dinormalisasi dengan sangat baik, itu hanya sangat tidak biasa, dan seperti yang ditunjukkan di tempat lain, RDBMS biasanya tidak dirancang untuk banyak kolom ini. .

Meskipun Anda tidak mencapai batas keras MySQL , salah satu faktor lain yang disebutkan dalam tautan mungkin mencegah Anda naik lebih tinggi

Seperti yang disarankan orang lain, Anda bisa mengatasi keterbatasan ini dengan memiliki tabel anak dengan id, sensor_id, sensor_value, atau lebih sederhana, Anda bisa membuat tabel kedua berisi hanya kolom yang tidak akan cocok di yang pertama (dan menggunakan PK yang sama)

Jack Douglas
sumber
1
Ini benar. Saat menangani data dan SQL yang sesuai dengan sangat hati-hati, jawaban Anda lebih menonjol !!!
RolandoMySQLDBA
3
Menggunakan tabel anak bukanlah "solusi". Memiliki satu kolom untuk setiap sensor adalah desain yang buruk (salah). Itu seperti memiliki satu kolom untuk setiap karyawan dalam sistem SDM, atau satu kolom untuk setiap produsen mobil untuk DB yang mengelola model mobil.
a_horse_with_no_name
11
@a_horse - Anda membuat asumsi yang saya ragu valid. Sangat mungkin bahwa jumlah sensor pada dasarnya diperbaiki, bahwa semua dibaca secara bersamaan dan semua data dikembalikan setiap waktu. Dalam hal ini satu kolom per sensor tidak "salah", hanya tidak praktis mengingat keterbatasan basis data. Saya suka berasumsi bahwa penanya bukan orang idiot sampai terbukti sebaliknya dan iUngi telah menanggapi dengan bermartabat di hadapan tanggapan yang sangat tidak membantu dari kerumunan SF.
Jack Douglas
2
@ Jack Douglas: bahkan jika semua asumsi Anda itu benar (yang saya sangat ragukan) menyimpan setiap nilai sensor di kolomnya sendiri akan menyebabkan masalah dalam jangka panjang. Bagaimana dengan pertanyaan seperti "berapa nilai rata-rata untuk sensor 10 hingga 50 dan 25 hingga 100 antara kemarin dan hari ini"? atau "Sensor mana yang memiliki nilai bacaan tertinggi Senin terakhir?". Cobalah untuk menulis kueri untuk ini dengan 2000 kolom. Menggunakan tabel yang dinormalisasi akan menyelesaikan lebih banyak masalah dalam jangka panjang daripada solusi 2000 kolom yang akan dipecahkan sekarang.
a_horse_with_no_name
2
Tentu, jika sensor menyimpan nilai terkait - saya berasumsi mereka tidak terkait (misalnya mereka semua mengukur berbagai hal daripada pada dasarnya hal yang sama di lokasi yang berbeda). Anda mungkin meragukannya, tetapi hanya OP yang tahu pasti - dan itu bukan tidak mungkin di bidang medis atau ilmiah.
Jack Douglas
15

Batas Jumlah Kolom MySQL 5.0 (penekanan ditambahkan):

Ada batas keras 4096 kolom per tabel , tetapi maksimum efektif mungkin kurang untuk tabel yang diberikan. Batas yang tepat tergantung pada beberapa faktor yang saling berinteraksi.

  • Setiap tabel (terlepas dari mesin penyimpanan) memiliki ukuran baris maksimum 65.535 byte. Mesin penyimpanan dapat menempatkan kendala tambahan pada batas ini, mengurangi ukuran baris maksimum yang efektif.

    Ukuran baris maksimum membatasi jumlah (dan kemungkinan ukuran) kolom karena panjang total semua kolom tidak dapat melebihi ukuran ini.

...

Mesin penyimpanan individual mungkin memberlakukan batasan tambahan yang membatasi jumlah kolom tabel. Contoh:

  • InnoDB memungkinkan hingga 1000 kolom.
lg_
sumber
7

Pertama beberapa lebih menyala, lalu solusi nyata ...

Saya sebagian besar setuju dengan api yang sudah dilemparkan pada Anda.

Saya tidak setuju dengan normalisasi nilai kunci. Pertanyaan akhirnya menjadi mengerikan; kinerja lebih buruk.

Salah satu cara 'sederhana' untuk menghindari masalah langsung (pembatasan jumlah kolom) adalah dengan 'mempartisi data' secara vertikal. Memiliki, katakanlah, 5 tabel dengan masing-masing 400 kolom. Mereka semua akan memiliki kunci utama yang sama, kecuali satu yang mungkin memiliki itu AUTO_INCREMENT.

Mungkin lebih baik untuk memutuskan selusin bidang yang paling penting, menempatkannya di tabel 'utama'. Kemudian kelompokkan sensor dengan cara yang logis dan masukkan ke dalam beberapa tabel paralel. Dengan pengelompokan yang tepat, Anda mungkin tidak perlu BERGABUNG dengan semua tabel sepanjang waktu.

Apakah Anda mengindeks salah satu nilai? Apakah Anda perlu mencarinya? Mungkin Anda mencari di datetime?

Jika Anda perlu mengindeks banyak kolom - punt.

Jika Anda perlu mengindeks beberapa - letakkan di tabel utama.

Inilah solusi nyata (jika itu berlaku) ...

Jika Anda tidak membutuhkan banyak sensor yang diindeks, maka jangan membuat kolom! Ya, kamu mendengarku. Alih-alih, kumpulkan mereka ke dalam JSON, kompres JSON, simpan di bidang BLOB. Anda akan menghemat banyak ruang; Anda hanya akan memiliki satu tabel, tanpa masalah batas kolom; dll. Aplikasi Anda akan terkompresi, dan kemudian menggunakan JSON sebagai struktur. Tebak apa? Anda dapat memiliki struktur - Anda dapat mengelompokkan sensor ke dalam array, hal-hal bertingkat, dll, seperti yang diinginkan aplikasi Anda. 'Fitur' lain - itu terbuka. Jika Anda menambahkan lebih banyak sensor, Anda tidak perlu mengubah tabel. JSON jika fleksibel seperti itu.

(Kompresi adalah opsional; jika dataset Anda besar, itu akan membantu dengan ruang disk, maka kinerja keseluruhan.)

Rick James
sumber
Inilah jawaban terbaik sebenarnya. Tidak apa-apa untuk berkomentar bahwa mungkin dia harus meneliti tidak memiliki banyak kolom, tetapi untuk jawaban yang diterima menjadi 'jangan lakukan itu' tidak menjawab pertanyaan. Bahkan jika orang ini tidak benar-benar membutuhkan banyak kolom, mungkin orang lain yang menemukan Q ini membutuhkan banyak, dan membutuhkan jawaban nyata.
BoB3K
@ BoB3K - Paragraf besar saya mengatakan apa yang harus dilakukan , mengingat informasi yang tersedia tentang masalah tersebut sebagaimana dinyatakan. JSONmenghindari "kolom terlalu banyak"; pengindeksan kolom yang dipilih membantu dengan kinerja.
Rick James
3

Saya melihat ini sebagai skenario yang mungkin terjadi di dunia data besar, di mana Anda mungkin tidak melakukan tipe query * pilih tradisional. Kami berurusan dengan ini dalam dunia pemodelan prediktif pada tingkat pelanggan di mana kami memodelkan pelanggan di ribuan dimensi (semuanya memiliki nilai 0 atau 1). Cara penyimpanan ini membuat kegiatan pembangunan model hilir dll lebih mudah ketika Anda memiliki faktor risiko di baris yang sama dan bendera hasil di baris yang sama juga .. Ini dapat dinormalisasi dari titik berdiri penyimpanan dengan struktur anak induk, tetapi model prediksi hilir perlu mengubahnya kembali menjadi skema datar. Kami menggunakan redshift yang melakukan penyimpanan kolom, jadi 1000+ kolom Anda saat Anda memuat data, sebenarnya disimpan dalam format kolom ...

Ada waktu dan tempat untuk desain ini. Benar. Normalisasi bukanlah solusi untuk setiap masalah.

BigDataGuy
sumber
Terima kasih atas komentarnya. Jika seseorang ingin melakukan analisis dengan gambar, bahkan sedikit gambar berwarna 16x16 piksel memerlukan 16 * 16 * 3 bilangan bulat antara 0 dan 255 (3 angka untuk menggambarkan warna dalam satu dari 16x16 piksel menggunakan warna RGB). Itu adalah 768 kolom hanya untuk data, yang mana seseorang perlu menambahkan kunci.
VictorZurkowski