it-swarm.asia

InnoDB membuat kesalahan tabel: "Ukuran baris terlalu besar"

Kami memiliki beberapa insinyur yang meratakan struktur db yang dinormalisasi menjadi tabel sementara untuk keperluan menghasilkan laporan. Kolom ditentukan sebagai TEXT NOT NULL (Saya tahu "mengapa mereka melakukan itu?"; Mari kita asumsikan bahwa kita sedang menangani ini).

Kami menggunakan MySQL 5.1.48 Community RHEL5 dengan plug-in InnoDB 1.0.9 di Linux.

Saat menggunakan MyISAM, kami tidak pernah menemukan batas ukuran tabel kolom maks atau panjang baris maks (selama penyelidikan kami telah mencapai batas kolom maks di 2598 (yang ke-2599 menyebabkan kesalahan 1117). Dengan InnoDB kami mencapai batas. Batas ini memanifestasikan saat membuat tabel (tidak ada penyisipan data) sebagai:

GALAT 1118 (42000) pada baris 1: Ukuran baris terlalu besar. Ukuran baris maksimum untuk tipe tabel yang digunakan, tidak termasuk BLOB, adalah 8126. Anda harus mengubah beberapa kolom menjadi TEXT atau BLOB

Saya mencari jawaban untuk yang berikut:

  1. Apa rumus terperinci untuk menentukan ukuran baris khususnya ketika menggunakan lot's dari kolom v/v/b/t? Saya telah mencoba beberapa formual yang berbeda menggunakan varchar(N) kolom (di mana N adalah antara 1 dan 512), charset UTF8 (* 3), dan sebanyak mungkin kolom yang dibutuhkan tabel sampai kegagalan. Tidak ada satu pun dari kombo yang saya coba berikan nilai yang cocok dengan hasil tes yang sebenarnya.

  2. Apa 'overhead' lain yang harus saya pertimbangkan ketika menghitung ukuran baris?

  3. Mengapa pesan kesalahan berubah dari 8126 ke 65535 ketika saya beralih dari membuat tabel dengan kolom varchar (109) ke kolom varchar (110)?

11
Evan

Jawaban atas pertanyaan Anda sangat kompleks, karena berbeda menurut InnoDB format file . Saat ini, ada dua format, yang disebut Antelope dan Barracuda.

File tablespace pusat (ibdata1) selalu dalam format Antelope . Jika Anda menggunakan file-per-tabel, Anda dapat membuat file individual menggunakan Barracuda format dengan mengatur innodb_file_format=Barracuda di my.cnf.

Poin dasar:

  • Satu halaman 16KB data InnoDB harus menampung setidaknya dua baris data. Plus setiap halaman memiliki header dan footer yang berisi checksum halaman dan nomor urut log dan sebagainya. Di situlah Anda mendapatkan batas Anda sedikit kurang dari 8KB per baris.

  • Tipe data ukuran tetap seperti INTEGER, DATE, FLOAT, CHAR disimpan pada halaman data primer ini dan dihitung menuju batas ukuran baris.

  • Tipe data berukuran variabel seperti VARCHAR, TEXT, BLOB disimpan pada halaman meluap, sehingga mereka tidak menghitung sepenuhnya menuju batas ukuran baris. Di Antelope, hingga 768 byte kolom seperti itu disimpan di halaman data primer selain disimpan di halaman overflow. Barracuda mendukung format baris dinamis , sehingga ia hanya dapat menyimpan pointer 20-byte pada halaman data primer.

  • Tipe data ukuran variabel juga diawali dengan 1 atau lebih byte untuk menyandikan panjangnya. Dan format baris InnoDB juga memiliki array offset bidang. Jadi ada struktur internal kurang lebih didokumentasikan dalam wiki mereka . [EDIT] Tautan mati - di sini terlihat lebih baik sekarang.

Barracuda juga mendukung ROW_FORMAT = COMPRESSED untuk mendapatkan efisiensi penyimpanan lebih lanjut untuk data luapan.

Saya juga harus berkomentar bahwa saya belum pernah melihat meja yang dirancang dengan baik melebihi batas ukuran baris. Ini adalah "bau kode" yang kuat yang Anda langgar kondisi kelompok berulang dari Bentuk Normal Pertama.

19
Bill Karwin

Situasi saya sedikit berbeda. Salah satu elemen data yang perlu saya simpan di setiap baris berpotensi sangat besar. (Bidang data adalah LONGBLOB untuk dokumen yang mungkin berisi banyak gambar yang disematkan. Basis data sampel saya berisi dokumen berukuran 25 - 30 MB, tetapi dalam beberapa kasus, dokumen ini bisa lebih besar.) Tidak ada solusi yang saya temukan online yang memberikan bantuan . (Mengubah tipe file InnoDB ke Barracuda, meningkatkan ukuran file log, mengatur format baris ke COMPRESSED.)

Satu-satunya solusi yang saya temukan yang berhasil bagi saya adalah kembali ke MySQL 5.5.x dari MySQL 5.6.x.

1
David