Pentingnya panjang varchar dalam tabel MySQL

112

Saya memiliki tabel MySQL di mana baris disisipkan secara dinamis. Karena saya tidak bisa memastikan panjang string dan tidak ingin mereka dipotong, saya membuatnya varchar (200) yang umumnya jauh lebih besar dari yang saya butuhkan. Apakah ada pencapaian kinerja yang besar dalam memberikan bidang varchar lebih panjang dari yang diperlukan?

Brian
sumber
Tabel dengan satu VARCHAR(255) utf8mb4kolom terindeks dengan ~ 150 ribu baris berukuran 11,5 MB. Tabel dengan VARCHAR(48) utf8mb4kolom terindeks dengan data yang sama (panjang maksimal 46 karakter) menggunakan 4,5MB. Bukan perbedaan besar dalam kueri, ini diindeks. Tapi itu bertambah dengan query I / O dan hal-hal seperti backup database.
Code4R7

Jawaban:

59

Tidak, dalam artian jika nilai yang Anda simpan di kolom tersebut selalu (katakanlah) kurang dari 50 karakter, menyatakan kolom sebagai varchar(50)atau varchar(200)memiliki kinerja yang sama.

Alex Martelli
sumber
9
Tidak sepenuhnya benar. Lihat jawaban Bill Karwin
hejdav
5
Saya pikir jawaban seperti itu harus didukung oleh dokumen, tolok ukur, atau yang serupa.
Gokhan Sari
301

Ada satu kemungkinan dampak kinerja: di MySQL, tabel dan tabel sementara MEMORYmenyimpan VARCHARkolom sebagai kolom dengan panjang tetap, dengan panjang maksimumnya. Jika Anda mendesain VARCHARkolom jauh lebih besar dari ukuran terbesar yang Anda butuhkan, Anda akan menghabiskan lebih banyak memori daripada yang Anda perlukan. Ini memengaruhi efisiensi cache, kecepatan penyortiran, dll.

Bill Karwin
sumber
33
+1. Saya juga melihat beberapa driver JDBC yang mengalokasikan cukup ruang untuk ukuran maksimum saat menyiapkan buffer untuk mengambil baris. Tak perlu dikatakan, ini menyebabkan banyak kegelisahan dan kertakan gigi ketika beberapa badut baru saja melakukan varchar (50000) kalau-kalau seseorang memiliki nama belakang yang sangat besar :-)
paxdiablo
21
+1. Ini adalah dampak penting dan saya yakin inilah jawaban sebenarnya dari pertanyaan ini.
Emre Yazici
6
Jawaban ini dan jawaban yang diterima keduanya diperlukan untuk memahami jawaban yang benar untuk OP.
kd8azz
2
Faktanya, ketika MEMORYtabel seperti itu dianggap terlalu besar, itu ditulis ke disk, menyebabkan penurunan kinerja yang signifikan.
Timo
1
Jawaban ini dapat dilakukan dengan menentukan mesin penyimpanan mana yang benar (saya perhatikan bahwa dev.mysql.com/doc/refman/8.0/en/… menunjukkan bahwa tabel sementara selalu InnoDB pada MySQL 8; apakah itu mengubah apa pun?) , dan dengan tautan ke dokumen yang mendukung klaim yang dibuatnya. Dari apa yang saya lihat tentang keluaran Anda di Stack Exchange, saya yakin Anda benar saat menulis ini, tetapi banyak hal mungkin telah berubah, dan tautan akan menjadi contoh yang baik bagi orang lain dan membantu mengajari kita semua untuk menemukannya informasi semacam ini untuk diri kita sendiri.
Mark Amery
14

VARCHAR ideal untuk situasi yang Anda gambarkan, karena itu singkatan dari "karakter variabel" - batas, berdasarkan contoh Anda, akan menjadi 200 karakter tetapi apa pun yang kurang dari itu diterima dan tidak akan mengisi ukuran kolom yang dialokasikan.

VARCHAR juga mengambil lebih sedikit ruang - nilai disimpan sebagai awalan satu byte atau dua byte plus data. Awalan panjang menunjukkan jumlah byte dalam nilai. Kolom menggunakan satu byte panjang jika nilai memerlukan tidak lebih dari 255 byte, dua panjang byte jika nilai mungkin memerlukan lebih dari 255 byte.

Untuk informasi lebih lanjut membandingkan tipe data MySQL CHAR dengan VARCHAR, lihat tautan ini .

OMG Ponies
sumber
1
semua orang yang tertarik pada penyimpanan MySQL (tentang CHAR dan VARCHAR) harus membaca tautan yang disebutkan dalam jawaban ini. Terima kasih!
Pascal
14

Ukuran adalah kinerja! Semakin kecil ukurannya, semakin baik. Bukan hari ini atau besok, tetapi suatu hari tabel Anda akan bertambah besar ketika menghadapi kemacetan serius, tidak peduli desain apa yang Anda tata. Tetapi Anda dapat meramalkan beberapa potensi hambatan dalam fase desain Anda yang kemungkinan besar akan terjadi terlebih dahulu dan mencoba untuk memperpanjang waktu db Anda akan bekerja dengan cepat dan bahagia sampai Anda perlu memikirkan ulang skema Anda atau menskalakan secara horizontal dengan menambahkan lebih banyak server.

Dalam kasus Anda, ada banyak kebocoran kinerja yang dapat Anda temui: Gabungan besar hampir tidak mungkin terjadi dengan waktu yang lama varchar kolom yang . Mengindeks kolom tersebut adalah pembunuh yang nyata. Disk Anda harus menyimpan data. Satu halaman memori dapat menampung lebih sedikit baris dan pemindaian tabel akan jauh lebih lambat. Juga cache kueri tidak akan membantu Anda di sini.

Anda harus bertanya pada diri sendiri: Berapa banyak penyisipan per tahun yang mungkin terjadi? Berapa panjang rata-rata? Apakah saya benar-benar membutuhkan lebih dari 200 karakter atau dapatkah saya menangkapnya di bagian depan aplikasi saya, bahkan dengan memberi tahu pengguna tentang panjang maksimum? Dapatkah saya membagi tabel menjadi tabel sempit untuk pengindeksan dan pemindaian cepat dan tabel lainnya untuk menyimpan data tambahan yang lebih jarang dibutuhkan untuk ukuran yang diperluas? Dapatkah saya mengetik data varchar yang mungkin ke dalam kategori dan mengekstrak beberapa data menjadi beberapa kolom yang lebih kecil, mungkin int atau bool-type dan mempersempit kolom varchar seperti itu?

Anda dapat melakukan banyak hal di sini. Mungkin yang terbaik adalah menggunakan asumsi pertama dan kemudian mendesain ulang langkah demi langkah menggunakan data kinerja terukur di kehidupan nyata. Semoga berhasil.

Dorongan
sumber
1 untuk membuat daftar opsi desain dan mengeksplorasi dampaknya. Sangat membantu untuk pertanyaan saya juga. stackoverflow.com/q/12083089/181638
Assad Ebrahim
5
Apakah ada dampak kinerja aktual dari pengaturan panjang maksimum tinggi, atau apakah kinerja hanya ditentukan oleh ukuran sebenarnya?
poolie
5

Performa? Tidak. Penyimpanan disk? Ya, tapi harganya murah dan berlimpah. Kecuali jika database Anda akan berkembang menjadi skala terabyte, Anda mungkin baik-baik saja.

duffymo
sumber
Aneh bahwa jawaban ini tidak disukai enam tahun setelah diposting dan tidak ada jawaban lainnya. Tampak pendendam dan picik. Tidak ada yang salah tentang jawaban ini. Moderator?
duffymo
1
Seperti yang dikatakan, hal itu memengaruhi kinerja. Selain itu, penyimpanan disk juga tidak gratis. Kolom yang lebih lebar berarti lebih banyak disk baca / tulis (dan akses disk slooooooow), dan juga indeks yang lebih luas, yang mengurangi kegunaannya. Kedua hal tersebut berdampak negatif pada kinerja. Mungkin hal itu dapat diabaikan pada database kecil, tetapi pada skala gigabyte / terabyte itu pasti akan menjadi masalah, seperti yang Anda katakan. Untuk tabel 100 register, itu tidak masalah.
Alejandro
5

Beberapa dari Anda salah mengira bahwa a varchar(200)membutuhkan lebih banyak ukuran tabel pada disk daripada a varchar(20). Ini bukan kasusnya. Hanya ketika Anda melampaui 255 karakter, mysql menggunakan byte tambahan untuk menentukan panjang varchardata lapangan.

DCH
sumber
9
Tidak demikian halnya untuk tabel dan tabel sementara MEMORY.
Balapan Ringan di Orbit
4
Kapan pun kueri pemilihan Anda menggunakan tabel sementara (kelompok dan urutan berdasarkan operasi, antara lain) itu akan mengonversi varchar (200) menjadi char (200) dan kinerja akan terganggu.
Jamie
1

Mungkin ada kinerja yang berhasil - tetapi biasanya tidak pada tingkat yang akan dilihat sebagian besar pengguna.

Ketika ukuran setiap kolom diketahui sebelumnya, MySQL tahu persis berapa banyak byte di antara setiap kolom / baris dan dapat meneruskan halaman tanpa membaca semua data. Menggunakan karakter variabel mengurangi kemampuan pengoptimalan ini.

Apakah varchar menghasilkan kinerja yang terpukul karena fragmentasi data?

Lebih baik lagi, char vs varchar .

Bagi sebagian besar menggunakan, Anda akan baik-baik dengan baik - tetapi ada adalah perbedaan, dan untuk database skala besar, ada alasan mengapa Anda akan memilih satu atau yang lain.

Rizwan Kassim
sumber
0

Menjadi varchar, bukan hanya char, ukurannya didasarkan pada bidang internal untuk menunjukkan panjang sebenarnya dan string itu sendiri. Jadi menggunakan varchar (200) tidak jauh berbeda dengan menggunakan varchar (150), kecuali Anda memiliki potensi untuk menyimpan lebih banyak.

Dan Anda harus mempertimbangkan apa yang terjadi pada pembaruan, ketika baris tumbuh. Tetapi jika ini jarang terjadi, maka Anda akan baik-baik saja.

Rob Farley
sumber
0

sesuai dengan nama tipe data menunjukkan ini adalah VARCHAR yaitu penyimpanan data karakter variabel, mesin mysql sendiri mengalokasikan memori yang digunakan sesuai data yang disimpan, jadi tidak ada kinerja yang dipukul sesuai pengetahuan saya.

pengguna2903114
sumber
0

Anda harus mencoba untuk melihat kolom varchar sama seperti Anda melihat kolom karakter di kebanyakan skenario dan mengatur panjangnya secara konservatif. Anda tidak harus selalu memikirkan pengubah var sebagai sesuatu yang memengaruhi pengambilan keputusan Anda secara maksimal. Ini benar-benar harus dilihat sebagai petunjuk kinerja alih-alih bahwa string yang disediakan akan memiliki panjang yang bervariasi.

Ini bukan arahan yang harus diikuti secara ketat oleh internal database, itu dapat diabaikan sepenuhnya. Berhati-hatilah dengan hal ini karena terkadang implementasi dapat bocor (panjang dan bantalan tetap misalnya) meskipun seharusnya tidak di dunia yang ideal.

Jika Anda memiliki varchar (255) maka Anda tidak memiliki jaminan bahwa performa bijaksana akan selalu berperilaku berbeda dengan char (255) dalam semua keadaan.

Tampaknya mudah untuk mengaturnya pada sesuatu seperti 255, 65535, dll, sejalan dengan saran yang diberikan dalam manual tentang persyaratan penyimpanan. Ini memberi kesan bahwa nilai apa pun antara 0 (ya, itu adalah hal) dan 255 akan memiliki dampak yang sama. Namun itu bukanlah sesuatu yang bisa dijamin sepenuhnya.

Persyaratan penyimpanan cenderung benar atau indikator yang baik untuk mesin penyimpanan persisten yang layak dan matang dalam hal penyimpanan baris. Ini bukan indikator yang kuat untuk hal-hal seperti indeks.

Ini terkadang pertanyaan yang sulit, tepatnya berapa panjang seutas benang sehingga memasangnya ke batas tertinggi yang Anda tahu seharusnya ada di dalam tetapi itu tidak berdampak. Sayangnya ini sering kali merupakan sesuatu yang diserahkan kepada pengguna untuk diselesaikan dan ini benar-benar sewenang-wenang. Anda tidak bisa benar-benar mengatakan tidak pernah terlalu besar string karena mungkin ada kasus di mana Anda tidak yakin.

Anda harus memastikan bahwa kueri MySQL menampilkan kesalahan saat string terlalu panjang daripada terpotong sehingga setidaknya Anda tahu jika terlalu pendek dari emisi kesalahan. Mengubah ukuran kolom untuk memperbesar atau memperkecilnya bisa menjadi operasi DDL yang mahal, hal ini harus diingat.

Set karakter juga harus dipertimbangkan di mana durasi dan kinerja berperan. Panjangnya mengacu pada ini daripada byte. Jika menggunakan utf8 misalnya, (bukan MB4) maka varchar (255) benar-benar varbinary (3 * 255). Sulit untuk mengetahui bagaimana hal-hal seperti ini akan benar-benar berjalan tanpa menjalankan tes dan melihat lebih dalam ke kode sumber / dokumentasi. Karena itu, ada ruang lingkup untuk panjang yang berlebihan untuk menimbulkan dampak yang meningkat secara tidak terduga. ini tidak hanya berlaku untuk kinerja. Jika suatu hari Anda perlu mengubah kumpulan karakter dari kolom varchar ke yang lebih besar maka Anda mungkin akan mencapai beberapa batas tanpa jalan lain jika Anda mengizinkan string yang sangat panjang untuk hadir yang bisa dihindari. Ini biasanya masalah yang cukup khusus tetapi muncul,

Jika ternyata MAX (PANJANG (kolom)) selalu <64 (seperti jika diputuskan akan ada batasan input yang tidak cocok dengan definisi kolom) tetapi Anda memiliki varchar (255) maka ada kemungkinan besar Anda akan menggunakan ruang empat kali lebih banyak dari yang dibutuhkan dalam beberapa skenario.

Ini mungkin termasuk:

  • Mesin yang berbeda, beberapa mungkin mengabaikannya sama sekali.
  • Ukuran penyangga, misalnya pembaruan atau penyisipan mungkin harus mengalokasikan 255 penuh (meskipun saya belum memeriksa kode sumber untuk membuktikan ini, itu hanya hipotetis).
  • Indeks, ini akan segera terlihat jika Anda mencoba membuat kunci komposit dari banyak kolom varchar (255).
  • Tabel perantara dan mungkin kumpulan hasil. Mengingat cara kerja transaksi, mungkin tidak selalu ada sesuatu yang menggunakan panjang maksimal string aktual dalam kolom sebagai lawan dari batas yang ditentukan.
  • Pengoptimalan prediksi internal mungkin memerlukan panjang maksimal sebagai input.
  • Perubahan versi implementasi database.

Sebagai aturan praktis, sebenarnya varchar tidak perlu lebih panjang dari yang seharusnya, masalah kinerja atau tidak, jadi saya sarankan untuk tetap menggunakannya saat Anda bisa. Mengambil lebih banyak upaya untuk mengambil sampel ukuran data Anda, menegakkan batas sebenarnya, atau mencari tahu batas sebenarnya melalui pertanyaan / penelitian adalah pendekatan yang ideal.

Ketika Anda tidak bisa, jika Anda ingin melakukan sesuatu seperti varchar (255) untuk kasus ketika ragu maka saya sarankan melakukan sains. Ini mungkin terdiri dari menduplikasi tabel, mengurangi ukuran kolom var char kemudian menyalin data ke dalamnya dari aslinya dan melihat ukuran data indeks / baris (indeks kolom juga, coba juga sebagai kunci utama yang mana mungkin berperilaku berbeda di InnoDB karena baris diurutkan berdasarkan kunci utama). Setidaknya dengan cara ini Anda akan tahu apakah Anda memiliki dampak pada IO yang cenderung menjadi salah satu hambatan paling sensitif. Menguji penggunaan memori lebih sulit, sulit untuk menguji itu secara menyeluruh. Saya akan merekomendasikan pengujian potensi kasus terburuk (kueri dengan banyak perantara dalam hasil memori, periksa dengan menjelaskan untuk tabel temp besar, dll).

Jika Anda tahu tidak akan ada banyak baris dalam tabel, Anda tidak akan menggunakan kolom untuk gabungan, indeks (terutama komposit, unik), dll. Maka kemungkinan besar Anda tidak akan mengalami banyak masalah.

jgmjgm
sumber