Apakah menyatakan VARCHAR
ukuran masuk akal untuk kinerja? Apakah ada perbedaan (dalam kecepatan) antara VARCHAR(50)
dan VARCHAR(255)
? Atau mendefinisikan panjang adalah batasan logika / desain?
mysql
database-design
Sonique
sumber
sumber
Jawaban:
Ini adalah "pertanyaan ujian / wawancara" yang sangat umum. Saya akan menjawab sebaik mungkin:
Dalam format baris standar untuk InnoDB dan MyISAM (dynamic / compact) a
VARCHAR(50)
dan aVARCHAR(255)
akan menyimpan teks string dengan cara yang sama - 1 byte untuk panjang dan string aktual dengan antara 1 dan 4 byte per karakter (tergantung pada pengkodean dan karakter aktual yang disimpan).Bahkan, jika saya ingat dengan benar, saya ingat seseorang memodifikasi kamus data dengan editor heksadesimal untuk mengubah sesuatu seperti
VARCHAR(50)
menjadiVARCHAR(100)
, sehingga bisa dilakukan secara dinamis (biasanya, yang memerlukan rekonstruksi tabel). Dan itu mungkin, karena data aktual tidak terpengaruh oleh perubahan itu.Itu tidak benar dengan
VARCHAR(256)
, karena dengan demikian 2 byte (setidaknya) untuk panjang selalu diperlukan.Jadi, itu berarti kita harus selalu melakukannya
VARCHAR(255)
, bukan? Tidak. Ada beberapa alasan.Sementara InnoDB dapat menyimpan varchar secara dinamis, itu tidak berlaku untuk mesin lain. MyISAM memiliki format ukuran baris tetap, dan tabel MEMORY selalu berukuran tetap. Haruskah kita peduli dengan mesin lain itu? Ya, kita harus, karena bahkan jika kita tidak menggunakannya secara langsung, tabel MEMORY sangat umum digunakan untuk hasil antara (tabel sementara pada memori) , dan karena hasilnya tidak diketahui sebelumnya, tabel harus dibuat dengan ukuran maksimum mungkin -
VARCHAR(255)
jika itu adalah tipe kami. Jika Anda dapat memikirkan ruang yang terbuang, jika kami menggunakan'utf8' charset
pengodean MySQL , MEMORY akan memesan 2 byte untuk panjang + 3 * 255 byte per baris(untuk nilai yang hanya membutuhkan beberapa byte pada InnoDB). Itu hampir 1GB di meja 1 juta - hanya untuk VARCHAR. Tidak hanya ini menyebabkan tekanan memori yang tidak perlu, itu dapat memicu tindakan yang harus dilakukan pada disk, berpotensi memperlambatnya ribuan kali. Semua itu karena pemilihan yang buruk dari tipe data yang didefinisikan (terlepas dari konten).Ini memiliki beberapa konsekuensi untuk InnoDB juga. Ukuran indeks dibatasi hingga 3072 byte dan indeks kolom tunggal, hingga 767 byte *. Jadi, sangat mungkin bahwa Anda tidak akan dapat mengindeks sepenuhnya
VARCHAR(255)
bidang (dengan asumsi Anda menggunakan utf8 atau pengodean panjang variabel lainnya).Selain itu, ukuran baris sebaris maksimum untuk InnoDB adalah setengah halaman (sekitar 8000 byte), dan bidang dengan panjang variabel seperti BLOB atau varchar, dapat disimpan di luar halaman jika tidak cocok dengan setengah halaman . Itu memiliki beberapa konsekuensi dalam kinerja (kadang-kadang baik, kadang-kadang buruk, tergantung pada penggunaan) yang tidak dapat diabaikan. Ini menyebabkan beberapa keanehan antara format COMPACT dan DYNAMIC. Lihat, misalnya: kesalahan 1118: ukuran baris terlalu besar. utf8 innodb
Last but not least, seperti @ypercube mengingatkan saya, lebih dari 1 byte untuk panjang mungkin diperlukan bahkan jika Anda menggunakan
VARCHAR(255)
, karena definisi dalam karakter, sedangkan panjang menyimpan byte. Sebagai contohREPEAT('ñ', 255)
memiliki lebih dari 2 ^ 255 byte dalam utf8, sehingga akan membutuhkan lebih dari 1 byte untuk menyimpan panjangnya:Jadi saran umum adalah menggunakan jenis terkecil yang mungkin , karena berpotensi dapat menciptakan masalah kinerja atau manajemen sebaliknya. A
VARCHAR(100)
lebih baik daripadaVARCHAR(255)
(meskipun aVARCHAR(20)
akan lebih baik), bahkan jika Anda tidak tahu panjang pastinya. Cobalah bersikap konservatif karena, kecuali jika tabelnya terlalu besar, Anda selalu dapat mengubah definisi nanti.Pembaruan: Karena popularitas yang meledak dari string panjang variabel, misalnya, dengan penggunaan emoji, Oracle telah mendorong peningkatan kinerja untuk kasus-kasus tersebut. Dalam versi MySQL terbaru (5.6, 5.7), InnoDB telah ditetapkan sebagai mesin default untuk tabel sementara intrinsik dan eksplisit yang berarti bahwa bidang panjang variabel sekarang menjadi warga negara kelas satu. Itu berarti bahwa mungkin ada sedikit alasan untuk memiliki panjang karakter yang sangat terbatas (tetapi itu masih ada).
(*) Pembaruan Kedua : large_prefix_index sekarang diaktifkan secara default pada versi MySQL terbaru (8.0), tetapi itu masih berlaku untuk versi yang lebih lama atau jika Anda menggunakan lagod innodb format file / baris (selain dinamis atau terkompresi), tetapi sekarang secara default, indeks kolom tunggal bisa mencapai 3072 byte.
sumber
Lupakan awalan 1- banding 2 byte
VARCHARs
.Pertanyaan tentang 255 telah diajukan dan dijawab berkali-kali.
VARCHARs
dapat menyebabkan kegagalanCREATE TABLE
.MEMORY
tabel, denganVARCHARs
diubah menjadiVARCHAR
. Ini berarti, misalnya, yangVARCHAR(255) CHARACTER SET utf8mb4
menginginkan panjang tetap 1020 byte. (Ini akan gagal, dan akan merosot untuk menggunakan MyISAM.)Intinya: Jangan gunakan secara buta 255 (atau 256); lakukan apa yang masuk akal untuk skema tersebut.
sumber