it-swarm.asia

Apa dampak kinerja menggunakan CHAR vs VARCHAR pada bidang ukuran tetap?

Saya memiliki kolom yang diindeks yang menyimpan hash MD5. Dengan demikian, kolom akan selalu menyimpan nilai 32 karakter. Untuk alasan apa pun, ini diciptakan sebagai varchar daripada char. Apakah sepadan dengan kesulitan memigrasi basis data untuk mengubahnya menjadi char? Ini di MySQL 5.0 dengan InnoDB.

60
Jason Baker

Pertanyaan serupa diajukan sebelumnya

Implikasi kinerja ukuran MySQL VARCHAR

Ini kutipan dari jawaban saya

Anda harus menyadari tradeoff menggunakan CHAR vs VARCHAR

Dengan bidang CHAR, apa yang Anda alokasikan adalah persis apa yang Anda dapatkan. Misalnya, CHAR (15) mengalokasikan dan menyimpan 15 byte, tidak peduli bagaimana karakter yang Anda tempatkan di bidang. Manipulasi string sederhana dan mudah karena ukuran bidang data benar-benar dapat diprediksi.

Dengan bidang VARCHAR, Anda mendapatkan cerita yang sama sekali berbeda. Misalnya VARCHAR (15) sebenarnya mengalokasikan secara dinamis hingga 16 byte, hingga 15 untuk data dan, setidaknya, 1 byte tambahan untuk menyimpan panjang data. Jika Anda memiliki string 'halo' untuk menyimpan yang akan mengambil 6 byte, bukan 5. Manipulasi string harus selalu melakukan beberapa bentuk pemeriksaan panjang dalam semua kasus.

Pengorbanan lebih jelas ketika Anda melakukan dua hal: 1. Menyimpan jutaan atau miliaran baris 2. Kolom pengindeksan yang CHAR atau VARCHAR

TRADEOFF # 1 Jelas, VARCHAR memegang keuntungan karena data panjang variabel akan menghasilkan baris yang lebih kecil dan, dengan demikian, file fisik yang lebih kecil.

TRADEOFF # 2 Karena bidang CHAR membutuhkan lebih sedikit manipulasi string karena lebar bidang tetap, pencarian indeks terhadap bidang CHAR rata-rata 20% lebih cepat daripada bidang VARCHAR. Ini bukan dugaan saya. Buku MySQL Database Design and Tuning melakukan sesuatu yang luar biasa pada tabel MyISAM untuk membuktikan ini. Contoh dalam buku ini melakukan sesuatu seperti berikut:

ALTER TABLE tblname ROW_FORMAT=FIXED;

Arahan ini memaksa semua VARCHAR berperilaku sebagai CHAR. Saya melakukan ini di pekerjaan saya sebelumnya pada tahun 2007 dan mengambil meja 300GB dan mempercepat pencarian indeks sebesar 20%, tanpa mengubah apa pun. Ini berfungsi seperti yang dipublikasikan. Namun, itu memang menghasilkan tabel hampir dua kali lipat, tetapi itu hanya kembali ke tradeoff # 1.

Anda bisa menganalisis data yang disimpan untuk melihat apa yang direkomendasikan MySQL untuk definisi kolom. Jalankan saja berikut ini di tabel mana saja:

SELECT * FROM tblname PROCEDURE ANALYSE();

Ini akan melintasi seluruh tabel dan merekomendasikan definisi kolom untuk setiap kolom berdasarkan data yang dikandungnya, nilai bidang minimum, nilai bidang maksimum, dan sebagainya. Terkadang, Anda hanya perlu menggunakan akal sehat dengan merencanakan CHAR vs VARCHAR. Ini adalah contoh yang bagus:

Jika Anda menyimpan alamat IP, mask untuk kolom seperti itu paling banyak 15 karakter (xxx.xxx.xxx.xxx). Saya akan melompat tepat di CHAR(15) dalam detak jantung karena panjang alamat IP tidak akan terlalu bervariasi dan kompleksitas tambahan dari manipulasi string dikontrol oleh byte tambahan. Anda masih bisa melakukan PROCEDURE ANALYSE() terhadap kolom seperti itu. Bahkan mungkin merekomendasikan VARCHAR. Uang saya masih di CHAR atas VARCHAR dalam hal ini.

Masalah CHAR vs VARCHAR hanya dapat diselesaikan melalui perencanaan yang tepat. Dengan kekuatan besar datang tanggung jawab besar (klise tapi benar).

MEMPERBARUI

Ketika datang ke MD5, perhitungan strlen secara internal harus dihilangkan ketika mengganti seluruh format baris. Tidak perlu mengubah definisi bidang.

Jika kunci MD5 adalah satu-satunya VARCHAR yang ada, saya akan menggunakannya dan mengonversi format baris tabel menjadi tetap . Jika ada jumlah signifikan bidang VARCHAR lain yang hadir, mereka akan mendapat manfaat juga. Sebagai gantinya, tabel akan berkembang menjadi sekitar dua kali ukurannya. Tetapi kueri harus mempercepat sekitar 20% lebih tanpa penyetelan tambahan.

57
RolandoMySQLDBA

Sepertinya Anda akan menghemat 1 byte per nilai atau sekitar 3% dengan mengonversi ke char. Mungkin tidak sepadan jika Anda menyimpan MD5 dalam hex - Anda bisa menghemat 50% dengan menggunakan binary sebagai gantinya.

Terima kasih kepada Ovais (lihat komentar) untuk menunjukkan bahwa char(32) dapat menggunakan lebih dari 32 byte jika Anda menggunakan rangkaian karakter multibyte.

Terima kasih kepada Rick James untuk menunjukkan bahwa Anda harus menggunakan fungsi unhex untuk mengubah string hex menjadi biner:

create table foo(bar varbinary(100));
insert into foo(bar) values(md5('a')); 
insert into foo(bar) values(unhex(md5('a'))); 
select length(bar) from foo;
 | panjang (bar) | 
 | ----------: | 
 | 32 | 
 | 16 | 

db <> biola di sini

Tidak ada gunanya mengubah pendapat saya. Jika Anda melihat dokumentasi di sini harus menggambarkan perbedaan antara keduanya. Dalam skenario penggunaan Anda, yang satu tidak benar-benar menawarkan manfaat yang signifikan di atas yang lain kecuali jika Anda benar-benar khawatir tentang sedikit biaya tambahan terkait dengan ukuran baris.

http://dev.mysql.com/doc/refman/5.0/id/char.html

Perhatikan juga komentar pertama pada dokumentasi yang saya tautkan di atas ... "CHAR hanya akan mempercepat akses Anda jika seluruh catatan adalah ukuran tetap. Artinya, jika Anda menggunakan objek ukuran variabel apa pun, Anda sebaiknya membuat semuanya ukuran variabel. Anda tidak mendapatkan kecepatan dengan menggunakan CHAR di tabel yang juga berisi VARCHAR "

15
RThomas