Apakah nilai kolom kosong menempati ruang penyimpanan yang sama dengan nilai kolom yang diisi?

15

Saya punya tabel dengan 2 kolom. Jenis kedua kolom diatur ke varchar(38). Jika saya membuat baris dengan nilai kosong untuk salah satu kolom, apakah akan mengambil ruang penyimpanan yang sama seolah-olah nilainya tidak kosong?

Dengan kata lain, akankah MySQL menyediakan ruang penyimpanan untuk kolom (tergantung pada jenisnya) ketika sebuah baris dibuat?

Haris ur Rehman
sumber

Jawaban:

11

Dari Struktur Baris Fisik Innodb, bulletpoint # 7 di bawah REDUNDANT ROW_FORMAT

Nilai SQL NULL menyimpan satu atau dua byte di direktori rekaman. Selain itu, nilai SQL NULL cadangan nol byte di bagian data catatan jika disimpan dalam kolom panjang variabel . Dalam kolom panjang tetap, ia menyimpan panjang tetap kolom di bagian data catatan. Dengan menyimpan ruang tetap untuk nilai NULL memungkinkan pembaruan kolom dari NULL ke nilai non-NULL dilakukan di tempat tanpa menyebabkan fragmentasi halaman indeks.

Dari Struktur Baris Fisik Innodb, bulletpoint # 2 di bawah COMPACT ROW_FORMAT

Bagian panjang variabel dari header catatan berisi vektor bit untuk menunjukkan kolom NULL. Jika jumlah kolom dalam indeks yang bisa NULL adalah N, vektor bit menempati CEILING (N / 8) byte . (Misalnya, jika ada 9 hingga 15 kolom yang dapat berupa NULL, vektor bit menggunakan dua byte.) Kolom yang NULL tidak menempati ruang selain bit dalam vektor ini . Bagian panjang variabel dari header juga berisi panjang kolom panjang variabel. Setiap panjang membutuhkan satu atau dua byte, tergantung pada panjang maksimum kolom. Jika semua kolom dalam indeks BUKAN NULL dan memiliki panjang tetap, header catatan tidak memiliki bagian panjang variabel.

Berdasarkan poin-poin ini, berikut adalah NULLnilai yang digunakan untuk penyimpanan kolom

  • panjang variabel: nilai NULL tidak menggunakan penyimpanan di baris itu sendiri
  • panjang tetap: Mengambil ruang yang dipesan

Sekarang, Anda harus memutuskan antara menggunakan CHAR dan VARCHAR karena apa yang dibawa poin pertama

Dengan mempertahankan ruang tetap untuk nilai NULL memungkinkan pembaruan kolom dari NULL ke nilai non-NULL dilakukan di tempat tanpa menyebabkan fragmentasi halaman indeks

Ini akan mencegah timbulnya fragmentasi dari suatu baris menurun ketika data non-NULL disimpan. Ini adalah sesuatu yang telah saya bahas sebelumnya mengenai MyISAM: Lihat posting lama saya Apa dampak kinerja menggunakan CHAR vs VARCHAR pada bidang ukuran tetap? .

RolandoMySQLDBA
sumber
Halo Rolando, ada item lain yang saya lupa sebutkan, perbedaan alokasi memori antara deklarasi tipe varchar (5) dan varchar (100). Atau benar-benar penalti yang ditimbulkan karena alokasi berlebihan.
Craig Efrein
@CraigEfrein Anda harus menambahkan alokasi memori ke jawaban Anda. (BTW saya sudah
mengangkat
1
Hukuman untuk alokasi berlebihan terjadi ketika Anda memiliki kompleks SELECTyang perlu membuat tabel temp. Jika memungkinkan, ini akan digunakan MEMORY, dan dikonversi VARCHARke CHARuntuk tabel tmp. Sekarang VARCHAR(100)mengambil 100 (atau 300) byte yang diperbaiki, sehingga mungkin memperlambat permintaan.
Rick James
@RolandoMySQLDBA, Apakah perilaku yang dijelaskan dalam jawaban Anda berlaku untuk format baris Mysql 5.7 DINAMIK dan KOMPAK.
Dinesh Kumar
@DineshKumar Paragraf-paragraf ini masih dalam 5,7 / 8,0 Docs. Silakan merujuk ke dev.mysql.com/doc/refman/5.7/en/innodb-row-format-dynamic.html untuk DYNAMIC.
RolandoMySQLDBA
8

Terlepas dari panjang yang Anda tentukan untuk kolom varchar Anda, ruang penyimpanan yang digunakan oleh kolom kosong akan sama.

Jenis CHAR dan VARCHAR

masukkan deskripsi gambar di sini

Ini hanya membahas ruang yang digunakan oleh kolom varchar dan tidak mempertimbangkan total ruang penyimpanan yang digunakan oleh baris, indeksnya, kunci primer dan kolom lainnya.

Seperti ypercube menyebutkan dalam komentarnya, ada pertimbangan tambahan untuk penyimpanan baris secara keseluruhan ketika setidaknya ada satu kolom yang dapat dibatalkan.

Struktur Baris Fisik Innodb

Bagian panjang variabel dari header catatan berisi vektor bit untuk menunjukkan kolom NULL. Jika ada 9 hingga 15 kolom yang bisa NULL, vektor bit menggunakan dua byte.)

...

Bagian panjang variabel dari header juga berisi panjang kolom panjang variabel. Setiap panjang membutuhkan satu atau dua byte, tergantung pada panjang maksimum kolom. Jika semua kolom dalam indeks BUKAN NULL dan memiliki panjang tetap, header catatan tidak memiliki bagian panjang variabel

Dan ya, ruang penyimpanan yang digunakan berubah berdasarkan pada jenis yang Anda pilih, apakah itu tetap atau variabel, pemeriksaan dan faktor-faktor lain seperti mesin.

MySQL membuat rekomendasi untuk mengoptimalkan penyimpanan data di sini: Mengoptimalkan Ukuran Data

Memperbarui

Satu pertimbangan tambahan dengan varchar dan itu adalah memori. Penting dalam MySQL untuk membatasi ukuran kolom panjang variabel sebanyak mungkin. Meskipun kolomnya variabel dan ruang penyimpanan yang digunakan adalah variabel, MySQL akan mengalokasikan memori dalam bentuk potongan tetap untuk menyimpan nilai. Misalnya varchar (200) akan menggunakan lebih banyak memori yang varchar (5). Ini bukan masalah ruang penyimpanan, tetapi masih sesuatu yang perlu dipertimbangkan saat mendefinisikan kolom Anda.

Craig Efrein
sumber
Angka-angka di atas mengasumsikan CHARACTER SETlatin1 atau ascii. Untuk utf8, Storage Wajib CHAR(4)adalah 12.
Rick James