Aku punya contacts
tabel yang berisi bidang-bidang seperti postcode
, first name
, last name
, town
, country
, phone number
dll, yang semuanya didefinisikan sebagai VARCHAR(255)
meskipun tak satu pun dari bidang-bidang ini akan pernah datang dekat untuk memiliki 255 karakter. (Jika Anda bertanya-tanya, begini karena migrasi Ruby on Rails memetakan bidang String ke VARCHAR(255)
secara default dan saya tidak pernah repot-repot menimpanya).
Karena VARCHAR hanya akan menyimpan jumlah karakter aktual dari bidang tersebut (bersama dengan panjang bidang), apakah ada keuntungan yang berbeda (kinerja atau sebaliknya) untuk menggunakan, katakanlah, VARCHAR(16)
lebih VARCHAR(255)
?
Selain itu, sebagian besar bidang ini memiliki indeks. Apakah ukuran VARCHAR yang lebih besar di lapangan mempengaruhi ukuran atau kinerja indeks sama sekali?
FYI Saya menggunakan MySQL 5.
Jawaban:
Dalam penyimpanan,
VARCHAR(255)
cukup pintar untuk menyimpan hanya panjang yang Anda butuhkan pada baris tertentu, tidak sepertiCHAR(255)
yang selalu menyimpan 255 karakter.Tetapi karena Anda menandai pertanyaan ini dengan MySQL, saya akan menyebutkan tip khusus MySQL: karena baris disalin dari lapisan mesin penyimpanan ke lapisan SQL,
VARCHAR
bidang diubahCHAR
untuk mendapatkan keuntungan dari bekerja dengan baris dengan lebar tetap. Jadi string dalam memori menjadi berlapis hingga panjang maksimumVARCHAR
kolom yang Anda nyatakan .Saat kueri Anda secara implisit menghasilkan tabel sementara, misalnya saat menyortir atau
GROUP BY
, ini bisa menggunakan banyak memori. Jika Anda menggunakan banyakVARCHAR(255)
bidang untuk data yang tidak perlu sepanjang itu, ini bisa membuat tabel sementara menjadi sangat besar.Anda mungkin juga ingin mengetahui bahwa perilaku "padding out" ini berarti bahwa string yang dideklarasikan dengan rangkaian karakter utf8 mengisi hingga tiga byte per karakter bahkan untuk string yang Anda simpan dengan konten byte tunggal (misalnya karakter ascii atau latin1). Dan juga set karakter utf8mb4 menyebabkan string menjadi empat byte per karakter dalam memori.
Jadi
VARCHAR(255)
dalam utf8 menyimpan string pendek seperti "Tidak ada opini" membutuhkan 11 byte pada disk (sepuluh karakter dengan karakter yang lebih rendah, ditambah satu byte untuk panjangnya) tetapi membutuhkan 765 byte dalam memori, dan dengan demikian dalam tabel temp atau hasil yang diurutkan.Saya telah membantu pengguna MySQL yang tanpa sadar sering membuat tabel temp 1,5GB dan mengisi ruang disk mereka. Mereka memiliki banyak
VARCHAR(255)
kolom yang dalam praktiknya menyimpan string yang sangat pendek.Sebaiknya tentukan kolom berdasarkan jenis data yang ingin Anda simpan. Ini memiliki manfaat untuk menegakkan batasan terkait aplikasi, seperti yang telah disebutkan orang lain. Tetapi memiliki manfaat fisik untuk menghindari pemborosan memori yang saya jelaskan di atas.
Sulit untuk mengetahui alamat pos yang paling panjang tentunya, itulah sebabnya banyak orang memilih panjang
VARCHAR
yang tentunya lebih panjang dari alamat manapun. Dan 255 adalah kebiasaan karena ini adalah panjang maksimum aVARCHAR
yang panjangnya dapat dikodekan dengan satu byte. Itu juga merupakanVARCHAR
panjang maksimum di MySQL yang lebih tua dari 5.0.sumber
255
digunakan agar panjang string bisa masuk ke dalam satu byteSelain pertimbangan ukuran dan kinerja dari pengaturan ukuran varchar (dan mungkin lebih penting, karena penyimpanan dan pemrosesan menjadi lebih murah setiap detik), kerugian menggunakan varchar (255) "hanya karena" adalah integritas data berkurang .
Menentukan batas maksimum untuk string adalah hal yang baik untuk dilakukan untuk mencegah string yang lebih panjang dari yang diharapkan memasuki RDBMS dan menyebabkan buffer overrun atau pengecualian / kesalahan nanti saat mengambil dan mengurai nilai dari database yang lebih panjang (lebih banyak byte) dari yang diharapkan.
Misalnya, jika Anda memiliki bidang yang menerima string dua karakter untuk singkatan negara, maka Anda tidak memiliki alasan untuk mengharapkan pengguna Anda (dalam konteks ini, pemrogram) untuk memasukkan nama negara secara lengkap. Karena Anda tidak ingin mereka memasukkan "Antigua dan Barbuda" (AG) atau "Pulau Heard dan Kepulauan McDonald" (HM), Anda tidak mengizinkannya di lapisan database. Juga, kemungkinan beberapa programmer belum melakukan RTFM untuk dokumentasi desain ( yang pasti ada ) untuk mengetahui untuk tidak melakukan ini.
Setel bidang untuk menerima dua karakter dan biarkan RDBMS menanganinya (baik secara anggun dengan memotong atau tidak dengan benar dengan menolak SQL mereka dengan kesalahan).
Contoh data nyata yang tidak memiliki alasan melebihi panjang tertentu:
Dan seterusnya...
Luangkan waktu untuk memikirkan data Anda dan batasannya. Jika Anda seorang arsitek, pengembang, atau programmer, itu adalah tugas Anda .
Dengan menggunakan varchar (n) dan bukan varchar (255) Anda menghilangkan masalah di mana pengguna (pengguna akhir, pemrogram, program lain) memasukkan data panjang yang tidak terduga yang akan kembali menghantui kode Anda nanti.
Dan saya tidak mengatakan Anda juga tidak harus menerapkan pembatasan ini dalam kode logika bisnis yang digunakan oleh aplikasi Anda.
sumber
the design documentation (which surely exists)
Hah. : DAku bersamamu. Perhatian yang cerewet terhadap detail adalah nyeri di leher dan memiliki nilai terbatas.
Dahulu kala, disk adalah komoditas yang berharga dan kami biasa mengeluarkan peluru untuk mengoptimalkannya. Harga penyimpanan telah turun dengan faktor 1.000, membuat waktu yang dihabiskan untuk memeras setiap byte menjadi kurang berharga.
Jika Anda hanya menggunakan bidang CHAR, Anda bisa mendapatkan baris dengan panjang tetap. Ini dapat menyimpan beberapa disk yang ditampilkan kembali secara nyata jika Anda memilih ukuran yang akurat untuk bidang. Anda mungkin mendapatkan data yang lebih padat (lebih sedikit I / O untuk pemindaian tabel) dan pembaruan yang lebih cepat (lebih mudah menemukan ruang terbuka di blok untuk pembaruan dan penyisipan.)
Namun, jika Anda memperkirakan ukuran Anda secara berlebihan, atau ukuran data Anda yang sebenarnya adalah variabel, Anda akan menghabiskan ruang dengan bidang CHAR. Data akan berakhir kurang padat (mengarah ke lebih banyak I / O untuk pengambilan besar).
Umumnya, manfaat kinerja dari upaya untuk meletakkan ukuran pada bidang variabel kecil. Anda dapat dengan mudah melakukan benchmark dengan menggunakan VARCHAR (255) dibandingkan dengan CHAR (x) untuk melihat apakah Anda dapat mengukur perbedaannya.
Namun, terkadang, saya perlu memberikan petunjuk "kecil", "sedang", "besar". Jadi saya menggunakan 16, 64, dan 255 untuk ukuran.
sumber
Saat ini, saya tidak bisa membayangkan itu benar-benar penting lagi.
Ada overhead komputasi untuk menggunakan kolom panjang variabel, tetapi dengan kelebihan CPU saat ini, itu bahkan tidak perlu dipertimbangkan. Sistem I / O sangat lambat sehingga membuat biaya komputasi apa pun untuk menangani varchars tidak ada secara efektif. Faktanya, harga varchar secara komputasi mungkin merupakan kemenangan bersih atas jumlah ruang disk yang disimpan dengan menggunakan bidang panjang variabel di atas bidang panjang tetap. Anda kemungkinan besar memiliki kepadatan baris yang lebih besar.
Sekarang, kerumitan bidang varchar adalah Anda tidak dapat dengan mudah menemukan data melalui nomor catatannya. Ketika Anda memiliki ukuran baris dengan panjang tetap (dengan bidang panjang tetap), sangat mudah untuk menghitung blok disk yang ditunjukkan oleh id baris. Dengan ukuran baris yang bervariasi, jenis seperti itu akan keluar jendela.
Jadi, sekarang Anda perlu mempertahankan beberapa jenis indeks nomor catatan, sama seperti kunci utama lainnya, ATAU Anda perlu membuat pengenal baris yang kuat yang mengkodekan detail (seperti blok, dll.) Ke pengenal. Jika Anda melakukannya, id harus dihitung ulang jika baris dipindahkan pada penyimpanan persisten. Bukan masalah besar, hanya perlu menulis ulang semua entri indeks dan memastikan Anda a) tidak pernah memaparkannya kepada konsumen atau b) tidak pernah menyatakan bahwa nomor tersebut dapat diandalkan.
Tetapi karena kita memiliki field varchar hari ini, satu-satunya nilai varchar (16) di atas varchar (255) adalah bahwa DB akan memberlakukan batas 16 karakter pada varchar (16). Jika model DB seharusnya benar-benar mewakili model data fisik, maka memiliki panjang bidang dapat menjadi nilai. Namun, jika itu hanya "penyimpanan" daripada "model DAN penyimpanan", tidak perlu sama sekali.
Kemudian Anda hanya perlu membedakan antara bidang teks yang dapat diindeks (seperti varchar) vs sesuatu yang tidak (seperti bidang teks atau CLOB). Bidang yang dapat diindeks cenderung memiliki batasan ukuran untuk memfasilitasi indeks sedangkan bidang CLOB tidak (dalam alasan).
sumber
Dalam pengalaman saya, jika Anda mengizinkan tipe data 255 karakter, beberapa pengguna bodoh (atau beberapa penguji berpengalaman) benar-benar akan mengisinya.
Kemudian Anda memiliki semua jenis masalah, termasuk berapa banyak ruang yang Anda izinkan untuk bidang tersebut dalam laporan dan tampilan di layar dalam aplikasi Anda. Belum lagi kemungkinan melebihi batas per baris untuk data dalam database Anda (jika Anda memiliki lebih dari beberapa bidang 255 karakter ini).
Jauh lebih mudah untuk memilih batas yang wajar di awal, kemudian menerapkannya melalui aplikasi dan database.
sumber
Merupakan praktik yang baik untuk mengalokasikan hanya sedikit lebih dari apa yang Anda butuhkan. Nomor telepon tidak akan pernah sebesar ini.
Salah satu alasannya adalah bahwa kecuali Anda memvalidasi terhadap entri yang besar, tidak diragukan lagi seseorang akan menggunakan semua yang ada. Kemudian Anda mungkin kehabisan ruang di baris Anda. Saya tidak yakin tentang batas MySQL tetapi 8060 adalah ukuran baris maksimum di MS SQL.
Default yang lebih normal adalah 50 imho, dan kemudian meningkat jika perlu membuktikannya.
sumber
Dalam konteks mysql, ini bisa menjadi penting ketika bekerja dengan indeks pada kolom varchar tersebut, karena mysql memiliki maks. batas 767 byte per baris-indeks.
Ini berarti bahwa ketika menambahkan indeks di beberapa kolom varchar 255 Anda bisa mencapai batas ini dengan agak cepat / bahkan lebih cepat pada kolom utf8 atau utf8mb4 seperti yang ditunjukkan pada jawaban di atas
sumber