Apa perbedaan antara tipe data MySQL VARCHAR dan TEXT?

19

Setelah versi 5.0.3 (yang memungkinkan VARCHAR menjadi 65.535 byte dan berhenti memotong ruang trailing), apakah ada perbedaan besar antara kedua tipe data ini?

Saya membaca daftar perbedaan dan hanya dua catatan adalah:

Untuk indeks pada kolom BLOB dan TEXT, Anda harus menentukan panjang awalan indeks. Untuk CHAR dan VARCHAR, panjang awalan adalah opsional. Lihat Bagian 7.5.1, “Indeks Kolom”.

dan

Kolom BLOB dan TEXT tidak dapat memiliki nilai DEFAULT.

Jadi, karena dua batasan ini pada datatype TEXT, mengapa Anda menggunakannya di varchar (65535)? Apakah ada konsekuensi kinerja satu di atas yang lain?

Derek Downey
sumber
1
kapan Anda ingin lebih dari 65535 karakter dalam data?
BlackICE
Berikut ini adalah utas forum yang cukup bagus tentang tolok ukur antara varchar dan teks: http://forums.mysql.com/read.php?24,105964,105964
dibagi
Karena daftar di sana benar-benar berfungsi dengan baik untuk memberikan rincian eksplisit, dan karena Anda sudah memiliki daftar perbedaan yang disebutkan, saya tidak yakin ini adalah jenis pertanyaan yang kami butuhkan di DBA. Apakah ada alasan bahwa daftar yang Anda kutip dan alasan yang Anda berikan tidak cukup baik dalam kasus ini? Kalau tidak, aku akan pergi ke VtC
jcolebrand
1
Saya memperbarui pertanyaan saya, tetapi satu alasan yang jelas bahwa saya tidak yakin adalah kinerja satu di atas yang lain. Tidak yakin apakah ada alasan lain yang tidak terlalu jelas
Derek Downey
Jadi, adilkah jika yang Anda tanyakan adalah karakteristik kinerja yang satu di atas yang lain?
jcolebrand

Jawaban:

13

dibagi terkait dengan beberapa info yang menjelaskan masalah dasar (ada perbedaan kinerja), tetapi tidak cukup sederhana untuk mengatakan bahwa seseorang selalu lebih baik daripada yang lain. (Jika tidak, tidak akan ada alasan untuk memiliki keduanya.) Juga, di MyISM, ukuran maksimal 64k untuk VARCHAR bukan per bidang - per rekaman.

Pada dasarnya, ada 4 cara untuk menyimpan string dalam catatan basis data:

  1. panjang tetap
  2. String gaya-C (ditandai dengan karakter NULL atau serupa di akhir string)
  3. String gaya pascal (beberapa byte untuk menunjukkan panjang, kemudian string)
  4. Pointer (simpan string di tempat lain)

MyISM menggunakan sesuatu yang mirip dengan # 3 untuk VARCHAR, dan pendekatan hybrid untuk TEXT di mana ia menyimpan awal string dalam catatan, lalu sisa string di tempat lain. InnoDB serupa untuk VARCHAR, tetapi menyimpan bidang TEKS lengkap di luar catatan.

Dengan 1 & 4, hal-hal dalam catatan selalu sama panjangnya, jadi lebih mudah untuk dilewati jika Anda tidak membutuhkan string, tetapi perlu hal-hal setelahnya. Baik # 2 dan # 3 tidak terlalu buruk untuk string pendek ... # 2 harus terus mencari penanda, sementara # 3 dapat melompat ke depan ... karena string semakin panjang, # 2 semakin buruk untuk penggunaan khusus ini kasus.

Jika Anda benar-benar perlu membaca string, # 4 lebih lambat, karena Anda harus membaca catatan, kemudian membaca string yang mungkin disimpan di tempat lain di disk, tergantung pada bagaimana database itu menanganinya. # 1 selalu sangat mudah, dan sekali lagi Anda mengalami masalah serupa di mana untuk # 2 semakin buruk semakin lama string, sedangkan # 3 sedikit lebih buruk daripada # 2 untuk string yang sangat kecil, tetapi lebih baik karena semakin lama.

Lalu ada persyaratan penyimpanan ... # 1 selalu merupakan panjang yang tetap, jadi mungkin akan menggembung jika sebagian besar string bukan panjang maksimal. # 2 memiliki 1 byte ekstra; # 3 biasanya memiliki 2 byte tambahan jika panjang maks = 255, 4 byte tambahan jika 64k maks. # 4 memiliki panjang pointer, ditambah aturan untuk # 3 biasanya.

Untuk implementasi spesifik dalam MySQL 5.1, dokumen untuk status MyISM :

  • Dukungan untuk tipe VARCHAR sejati; kolom VARCHAR dimulai dengan panjang yang disimpan dalam satu atau dua byte.
  • Tabel dengan kolom VARCHAR mungkin memiliki panjang baris tetap atau dinamis.
  • Jumlah dari panjang kolom VARCHAR dan CHAR dalam sebuah tabel bisa mencapai 64KB.

Sedangkan untuk InnoDB :

  • 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 bisa 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.
  • Untuk setiap bidang panjang variabel non-NULL, header catatan berisi panjang kolom dalam satu atau dua byte. Dua byte hanya akan diperlukan jika bagian dari kolom disimpan secara eksternal di halaman meluap atau panjang maksimum melebihi 255 byte dan panjang sebenarnya melebihi 127 byte. Untuk kolom yang disimpan secara eksternal, panjang dua byte menunjukkan panjang bagian yang disimpan secara internal ditambah penunjuk 20-byte ke bagian yang disimpan secara eksternal. Bagian internal 768 byte, jadi panjangnya 768 + 20. Pointer 20 byte menyimpan panjang kolom yang sebenarnya.

...

seperti halnya banyak hal lain ketika berurusan dengan basis data, jika Anda tidak yakin apa yang terbaik untuk kebutuhan Anda, cobalah membandingkannya dengan data & penggunaan yang serupa, dan lihat bagaimana perilakunya.

Joe
sumber
Utas yang terbagi terkait menyatakan bahwa MySQL menyimpan gumpalan dan bidang teks pada forum inline.mysql.com/read.php?24,105964,267596#msg-267596
Michael Mior
1
Nitpick ... Untuk semua tujuan praktis, tidak ada batasan 64KB pada satu baris di salah satu Engine. LONGTEXTdan LONGBLOBmerupakan contoh kasus. String C-style tidak digunakan oleh MySQL (yang saya tahu). InnoDB memang menggunakan pendekatan 'hybrid', tetapi lebih kompleks, tergantung pada ukuran baris, row_format, dll. Menyimpan string dalam panjang "tetap" hampir tidak pernah disarankan kecuali ketika mereka benar-benar panjang konstan (country_code, zip_code, dll) . InnoDB memiliki 4 ROW_FORMATs; teks hanya membahas 1 atau 2 darinya.
Rick James
2

Ketika SELECT perlu membuat tabel sementara (seperti untuk mengurutkan hasil), itu akan membuat tabel MEMORY, atau tabel MyISAM. MEMORY lebih efisien. Ada batasan pada MEMORY - satu adalah untuk melarang TEXT dan BLOB. Oleh karena itu, SELECT dapat berjalan lebih lambat dengan TEXT daripada VARCHAR.

Rick James
sumber