Praktik terbaik untuk panjang kolom SQL varchar [ditutup]

288

Setiap kali mengatur tabel SQL baru atau menambahkan varcharkolom baru ke tabel yang ada, saya bertanya-tanya satu hal: apa nilai terbaik untuk length.

Jadi, katakanlah, Anda memiliki kolom bernama nametype varchar. Jadi, Anda harus memilih panjangnya. Saya tidak bisa memikirkan nama> 20 karakter, tetapi Anda tidak akan pernah tahu. Tapi alih-alih menggunakan 20, saya selalu membulatkan ke angka 2 berikutnya. Dalam hal ini, saya akan memilih 32 sebagai panjangnya. Saya melakukan itu, karena dari sudut pandang ilmuwan komputer, angka 2 terlihat lebih evenbagi saya daripada angka lainnya dan saya hanya berasumsi bahwa arsitektur di bawahnya dapat menangani angka-angka itu sedikit lebih baik daripada yang lain.

Di sisi lain, server MSSQL misalnya, menetapkan nilai panjang default menjadi 50, ketika Anda memilih untuk membuat kolom varchar. Itu membuat saya memikirkannya. Mengapa 50? apakah itu hanya angka acak, atau berdasarkan panjang kolom rata-rata, atau apa?

Bisa juga - atau mungkin - bahwa implementasi SQL server yang berbeda (seperti MySQL, MSSQL, Postgres, ...) memiliki nilai panjang kolom terbaik yang berbeda.

esskar
sumber

Jawaban:

238

Tidak ada DBMS yang saya tahu memiliki "optimasi" yang akan membuat VARCHARdengan 2^npanjang berkinerja lebih baik daripada yang dengan maxpanjang yang bukan kekuatan 2.

Saya pikir versi SQL Server awal sebenarnya diperlakukan VARCHARdengan panjang 255 berbeda dari yang dengan panjang maksimum lebih tinggi. Saya tidak tahu apakah ini masih terjadi.

Untuk hampir semua DBMS, penyimpanan aktual yang diperlukan hanya ditentukan oleh jumlah karakter yang Anda masukkan, bukan maxpanjang yang Anda tentukan. Jadi dari sudut pandang penyimpanan (dan kemungkinan besar kinerja juga), tidak ada bedanya apakah Anda mendeklarasikan kolom sebagai VARCHAR(100)atau VARCHAR(500).

Anda harus melihat maxpanjang yang disediakan untuk VARCHARkolom sebagai semacam kendala (atau aturan bisnis) daripada hal teknis / fisik.

Untuk PostgreSQL pengaturan terbaik adalah menggunakan texttanpa batasan panjang dan CHECK CONSTRAINTyang membatasi jumlah karakter untuk apa pun yang dibutuhkan bisnis Anda.

Jika persyaratan itu berubah, mengubah batasan pemeriksaan jauh lebih cepat daripada mengubah tabel (karena tabel tidak perlu ditulis ulang)

Hal yang sama dapat diterapkan untuk Oracle dan lainnya - di Oracle itu akan menjadi VARCHAR(4000)bukan text.

Saya tidak tahu apakah ada perbedaan penyimpanan fisik antara VARCHAR(max)dan misalnya VARCHAR(500)dalam SQL Server. Namun ternyata ada dampak kinerja saat menggunakan varchar(max)dibandingkan dengan varchar(8000).

Lihat tautan ini (diposting oleh Erwin Brandstetter sebagai komentar)

Edit 2013-09-22

Mengenai komentar bigown:

Dalam Postgres versi sebelum 9.2 (yang tidak tersedia ketika saya menulis jawaban awal) perubahan ke definisi kolom melakukan menulis ulang seluruh meja, lihat misalnya di sini . Sejak 9,2 ini tidak lagi terjadi dan tes cepat menegaskan bahwa meningkatkan ukuran kolom untuk tabel dengan 1,2 juta baris memang hanya butuh 0,5 detik.

Bagi Oracle hal ini tampaknya benar juga, dilihat dari waktu yang diperlukan untuk mengubah varcharkolom tabel besar . Tetapi saya tidak dapat menemukan referensi untuk itu.

Untuk MySQL , manual mengatakan " Dalam kebanyakan kasus, ALTER TABLEbuat salinan sementara dari tabel asli ". Dan tes saya sendiri mengkonfirmasi bahwa: menjalankan sebuah ALTER TABLEdi atas meja dengan 1,2 juta baris (sama seperti dalam pengujian saya dengan Postgres) untuk meningkatkan ukuran kolom butuh 1,5 menit. Namun di MySQL Anda tidak dapat menggunakan "solusi" untuk menggunakan batasan pemeriksaan untuk membatasi jumlah karakter dalam kolom.

Untuk SQL Server saya tidak dapat menemukan pernyataan yang jelas tentang ini tetapi waktu eksekusi untuk meningkatkan ukuran varcharkolom (sekali lagi tabel 1,2 juta baris dari atas) menunjukkan bahwa tidak ada penulisan ulang yang terjadi.

Edit 2017-01-24

Sepertinya saya (setidaknya sebagian) salah tentang SQL Server. Lihat jawaban ini dari Aaron Bertrand yang menunjukkan bahwa panjang nvarcharatau varcharkolom yang dinyatakan membuat perbedaan besar untuk kinerja.

seekor kuda tanpa nama
sumber
34
Sebenarnya, ada perbedaan antara VARCHAR (255) dan VARCHAR (500), bahkan jika Anda memasukkan 1 karakter di dalam kolom tersebut. Nilai yang ditambahkan di akhir baris akan berupa bilangan bulat yang menyimpan berapa panjang sebenarnya data yang disimpan. Dalam kasus VARCHAR (255) itu akan menjadi 1 byte integer. Dalam hal VARCHAR (500) akan menjadi 2 byte. itu perbedaan kecil, tetapi orang harus menyadarinya. Saya tidak memiliki data tentang bagaimana hal itu dapat memengaruhi kinerja, tetapi saya menganggapnya sangat kecil sehingga tidak layak untuk diteliti.
NB
1
@ NB: itulah yang saya maksudkan untuk nilai "ajaib" SQL Server. Terimakasih atas klarifikasinya.
a_horse_with_no_name
4
@NB RDBMS mana yang Anda maksud? SQL Server? Ada efek pada kinerja. [N] VARCHAR (maks) berkinerja sedikit lebih lambat dari [N] VARCHAR (n). Saya baru saja dirujuk ke situs ini . Hal yang sama tidak berlaku untuk PostgreSQL untuk semua yang saya tahu.
Erwin Brandstetter
@ ErwinBrandstetter: Terima kasih atas tautannya. Sepertinya varchar(max)mungkin lebih mirip OracleCLOB
a_horse_with_no_name
1
Ubah panjang varchar tidak menulis ulang tabel. Itu hanya memeriksa panjang kendala terhadap seluruh tabel persis seperti PERIKSA KONSTRAINT. Jika Anda menambah panjang tidak ada yang bisa dilakukan, masukkan saja berikutnya atau pembaruan akan menerima panjang lebih besar. Jika Anda mengurangi panjang dan semua baris melewati batasan baru yang lebih kecil, Pg tidak mengambil tindakan lebih lanjut selain untuk membiarkan sisipan atau pembaruan berikutnya hanya menulis panjang baru.
Maniero
69

VARCHAR(255)dan VARCHAR(2)ambil jumlah ruang yang sama persis di disk! Jadi satu-satunya alasan untuk membatasi itu adalah jika Anda memiliki kebutuhan khusus untuk menjadi lebih kecil. Kalau tidak, buat semuanya 255.

Khususnya, ketika melakukan penyortiran, kolom yang lebih besar memang membutuhkan lebih banyak ruang, jadi jika itu mengganggu kinerja, maka Anda perlu khawatir tentang hal itu dan membuatnya lebih kecil. Tetapi jika Anda hanya pernah memilih 1 baris dari tabel itu, maka Anda bisa membuat semuanya 255 dan itu tidak masalah.

Lihat: Berapa ukuran varchar optimal untuk MySQL?

Ariel
sumber
7
Mengapa tidak membuat semuanya VARCHAR(MAX)? Space bukan satu-satunya pertimbangan saat memodelkan basis data. Domain model Anda harus mengarahkan tipe data dan ukurannya.
Oded
6
@Oded VARCHAR(MAX)tidak sama dengan varchar(255)atau varchar(65535)- varchar max adalah tipe texttipe data. Dan untuk titik Anda - jika dia tahu apa "domain yang dia modelkan" dia tidak akan menanyakan pertanyaan ini. Jelas dia tidak tahu seberapa besar datanya akan didapat, dan saya meyakinkannya bahwa menjadikannya ukuran penuh tidak ada salahnya.
Ariel
4
@Ririel: Ada masalah dan batasan indeks yang harus dipertimbangkan juga. Anda tidak dapat memiliki (a,b,c,d)indeks saat keempat kolom berada VARCHAR(255).
ypercubeᵀᴹ
@ypercube Itu benar, jika kolom Anda memerlukan indeks Anda harus lebih berhati-hati dengan ukuran. Tetapi sebagian besar kolom tidak memerlukan indeks sehingga sebagian besar waktu Anda tidak perlu khawatir tentang itu.
Ariel
Saya pikir jika kita tahu nilai pasti saya lebih suka menggunakan char. Sementara itu jika masih diprediksi saya menggunakan varchar dan menyimpan 255 karena ini adalah alokasi memori dinamis sehingga Anda tidak perlu khawatir tentang ukuran yang akan diambil
Faris Rayhan
54

Setiap kali saya membuat tabel SQL baru saya merasakan hal yang sama tentang 2 menjadi lebih "bahkan" ... tetapi untuk meringkas jawaban di sini, tidak ada dampak yang signifikan pada ruang penyimpanan hanya dengan mendefinisikan varchar (2 ^ n) atau bahkan varchar (MAX).

Yang mengatakan, Anda harus tetap mengantisipasi implikasi potensial pada penyimpanan dan kinerja ketika menetapkan batas varchar () yang tinggi. Misalnya, katakanlah Anda membuat kolom varchar (MAX) untuk menyimpan deskripsi produk dengan pengindeksan teks lengkap. Jika 99% deskripsi hanya panjang 500 karakter, dan tiba-tiba Anda mendapatkan seseorang yang menggantikan deskripsi dengan artikel wikipedia, Anda mungkin melihat penyimpanan signifikan dan hit kinerja yang tak terduga.

Hal lain yang perlu dipertimbangkan dari Bill Karwin :

Ada satu dampak kinerja yang mungkin terjadi: di MySQL, tabel sementara dan tabel MEMORY menyimpan kolom VARCHAR sebagai kolom dengan panjang tetap, yang disesuaikan dengan panjang maksimalnya. Jika Anda mendesain kolom VARCHAR jauh lebih besar dari ukuran terbesar yang Anda butuhkan, Anda akan menggunakan lebih banyak memori daripada yang seharusnya. Ini memengaruhi efisiensi cache, kecepatan penyortiran, dll.

Pada dasarnya, hanya datang dengan kendala bisnis yang wajar dan kesalahan pada ukuran yang sedikit lebih besar Seperti @onedaywhen tunjukkan, nama keluarga di Inggris biasanya antara 1-35 karakter. Jika Anda memutuskan untuk membuatnya menjadi varchar (64), Anda tidak akan menyakiti apa pun ... kecuali jika Anda menyimpan nama keluarga orang ini yang panjangnya mencapai 666 karakter. Dalam hal ini, mungkin varchar (1028) lebih masuk akal.

Dan jika itu membantu, inilah yang akan terlihat seperti varchar 2 ^ 5 hingga 2 ^ 10 jika diisi:

varchar(32)     Lorem ipsum dolor sit amet amet.

varchar(64)     Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie

varchar(128)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas

varchar(256)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt

varchar(512)    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie

varchar(1024)   Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donecie
                vestibulum massa. Nullam dignissim elementum molestie. Vehiculas
                velit metus, sit amet tristique purus condimentum eleifend. Quis
                que mollis magna vel massa malesuada bibendum. Proinde tincidunt
                dolor tellus, sit amet porta neque varius vitae. Seduse molestie
                lacus id lacinia tempus. Vestibulum accumsan facilisis lorem, et
                mollis diam pretium gravida. In facilisis vitae tortor id vulput
                ate. Proin ornare arcu in sollicitudin pharetra. Crasti molestie
                dapibus leo lobortis eleifend. Vivamus vitae diam turpis. Vivamu
                nec tristique magna, vel tincidunt diam. Maecenas elementum semi
                quam. In ut est porttitor, sagittis nulla id, fermentum turpist.
                Curabitur pretium nibh a imperdiet cursus. Sed at vulputate este
                proin fermentum pretium justo, ac malesuada eros et Pellentesque
                vulputate hendrerit molestie. Aenean imperdiet a enim at finibus
                fusce ut ullamcorper risus, a cursus massa. Nunc non dapibus vel
                Lorem ipsum dolor sit amet, consectetur Praesent ut ultrices sit
Kit
sumber
31

Nilai terbaik adalah yang tepat untuk data sebagaimana didefinisikan dalam domain yang mendasarinya.

Untuk beberapa domain, VARCHAR(10)tepat untuk Nameatribut, untuk domain lain VARCHAR(255)mungkin merupakan pilihan terbaik.

Oded
sumber
15

Menambahkan ke jawaban a_horse_with_no_name Anda mungkin menemukan yang menarik berikut ...

tidak ada bedanya apakah Anda mendeklarasikan kolom sebagai VARCHAR (100) atau VACHAR (500).

-- try to create a table with max varchar length
drop table if exists foo;
create table foo(name varchar(65535) not null)engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length - 2 bytes for the length
drop table if exists foo;
create table foo(name varchar(65533) not null)engine=innodb;

Executed Successfully

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65533))engine=innodb;

MySQL Database Error: Row size too large.

-- try to create a table with max varchar length with nullable field
drop table if exists foo;
create table foo(name varchar(65532))engine=innodb;

Executed Successfully

Jangan lupa byte panjang dan byte nullable jadi:

name varchar(100) not null akan menjadi 1 byte (panjang) + hingga 100 karakter (latin1)

name varchar(500) not null akan menjadi 2 byte (panjang) + hingga 500 karakter (latin1)

name varchar(65533) not null akan menjadi 2 byte (panjang) + hingga 65533 karakter (latin1)

name varchar(65532) akan menjadi 2 byte (panjang) + hingga 65532 karakter (latin1) + 1 byte nol

Semoga ini membantu :)

Jon Black
sumber
Anda menggunakan MySQL, dan pertanyaannya adalah tentang MSSQL
Bogdan Mart
6

Selalu periksa dengan pakar domain bisnis Anda. Jika itu Anda, cari standar industri. Jika, misalnya, domain yang dimaksud adalah nama keluarga orang asli (nama keluarga) maka untuk bisnis di Inggris saya akan pergi ke katalog standar data UK Govtalk untuk informasi orang dan menemukan bahwa nama keluarga akan antara 1 dan 35 karakter .

suatu hari nanti
sumber
3

Saya belum memeriksa ini akhir-akhir ini, tetapi saya tahu di masa lalu dengan Oracle bahwa driver JDBC akan memesan sepotong memori selama eksekusi permintaan untuk menahan hasil set kembali. Ukuran potongan memori tergantung pada definisi kolom dan ukuran pengambilan. Jadi panjang kolom varchar2 memengaruhi berapa banyak memori yang dipesan. Ini menyebabkan masalah kinerja serius bagi saya bertahun-tahun yang lalu karena kami selalu menggunakan varchar2 (4000) (maks pada saat itu) dan pengumpulan sampah jauh lebih efisien daripada sekarang.

pengguna1041892
sumber
-2

Dalam arti Anda benar, meskipun apa pun yang lebih rendah dari 2 ^ 8 karakter masih akan mendaftar sebagai byte data.

Jika Anda memperhitungkan karakter dasar yang meninggalkan apa pun dengan VARCHAR <255 karena mengonsumsi jumlah ruang yang sama.

255 adalah definisi dasar yang baik kecuali Anda secara khusus ingin mengurangi input yang berlebihan.

Dale Willis
sumber
" walaupun sesuatu yang lebih rendah dari 2 ^ 8 karakter masih akan mendaftar sebagai byte data " - salah. Basis data hanya menyimpan karakter sebanyak yang disediakan dalam tipe VARCHAR. Tidak ada ruang yang "terdaftar", dipesan atau diinisialisasi ketika mendeklarasikan kolom.
a_horse_with_no_name