apakah ada keuntungan dari varchar (500) dibandingkan varchar (8000)?

90

Saya telah membaca ini di forum MSDN dan di sini dan saya masih belum jelas. Saya pikir ini benar: Varchar (max) akan disimpan sebagai tipe data teks, sehingga memiliki kekurangan. Jadi katakanlah bidang Anda bisa diandalkan di bawah 8000 karakter. Seperti bidang BusinessName di tabel database saya. Pada kenyataannya, nama bisnis mungkin akan selalu di bawah (menarik nomor dari topi saya) 500 karakter. Sepertinya banyak bidang varchar yang saya temui termasuk dalam jumlah karakter 8k.

Jadi, haruskah saya membuat bidang itu menjadi varchar (500), bukan varchar (8000)? Dari apa yang saya pahami tentang SQL, tidak ada perbedaan antara keduanya. Jadi, untuk membuat hidup lebih mudah, saya ingin mendefinisikan semua field varchar saya sebagai varchar (8000). Apakah itu ada kekurangannya?

Terkait: Ukuran kolom varchar (saya tidak merasa yang ini menjawab pertanyaan saya).

jcollum.dll
sumber
6
Bayangkan mencoba memasukkan nama bisnis sepanjang 500 karakter pada kartu bisnis ... :)
OMG Ponies
2
@OMG Ponies: setiap kali saya melihat nama pengguna Anda, saya tertawa. Sekarang, apa yang kamu katakan? (Hanya bercanda)
jcollum
4
@jcollum: SpaceMan Spiff akan selalu mendapatkan suara saya. Itu tidak benar - setiap Calvin & Hobbes akan lakukan, tetapi terutama salju patung yang. Atau tyranosaurus yang menerbangkan F-14. Tapi aku ngelantur ...
OMG Ponies

Jawaban:

20

Dari sudut pandang pemrosesan, tidak ada bedanya untuk menggunakan varchar (8000) vs varchar (500). Ini lebih merupakan jenis "praktik yang baik" untuk menentukan panjang maksimum yang harus dipegang sebuah bidang dan membuat varchar Anda sepanjang itu. Itu adalah sesuatu yang dapat digunakan untuk membantu validasi data. Misalnya membuat singkatan negara bagian menjadi 2 karakter atau kode pos / pos sebanyak 5 atau 9 karakter. Ini digunakan untuk menjadi perbedaan yang lebih penting ketika data Anda berinteraksi dengan sistem lain atau antarmuka pengguna di mana panjang bidang sangat penting (misalnya set data file datar mainframe), tetapi saat ini saya pikir itu lebih merupakan kebiasaan daripada yang lain.

BBlake
sumber
3
Masuk akal ... untuk hal-hal yang secara alami memiliki panjang maksimum. Tapi apa yang Anda lakukan saat panjang maksimal tidak jelas? Misalnya nama bisnis.
jcollum
2
Untuk hal seperti itu, jika saya tidak meramalkan cara apa pun untuk memperkirakan ukuran potensial apa pun, maka saya biasanya akan menggunakan varchar (8000) atau varchar (maks), tergantung pada jenis datanya
BBlake
4
Tampaknya hal ini membuat perbedaan dalam kinerja, bahkan di tahun 2017: dba.stackexchange.com/a/162117/1822
a_horse_with_no_name
2
Jawaban yang lebih baru menunjukkan bahwa ada yang biaya: itu mempengaruhi optimasi logika jawaban Martin Smith dan juga mempertimbangkan 8K Total masalah ukuran baris yang disebutkan oleh gbn dan Oliver .
ToolmakerSteve
124

Salah satu contoh di mana hal ini dapat membuat perbedaan adalah dapat mencegah pengoptimalan kinerja yang menghindari penambahan informasi pembuatan versi baris ke tabel dengan pemicu setelahnya.

Ini tercakup dalam SQL Kiwi di sini

Ukuran sebenarnya dari data yang disimpan tidak material - yang penting adalah ukuran potensial.

Demikian pula jika menggunakan tabel yang dioptimalkan memori sejak 2016, dimungkinkan untuk menggunakan kolom LOB atau kombinasi lebar kolom yang berpotensi melebihi batas inrow tetapi dengan penalti.

(Maks) kolom selalu disimpan di luar baris. Untuk kolom lain, jika ukuran baris data dalam definisi tabel dapat melebihi 8.060 byte, SQL Server mendorong kolom dengan panjang variabel terbesar di luar baris. Sekali lagi, ini tidak tergantung pada jumlah data yang Anda simpan di sana.

Ini dapat berdampak negatif besar pada konsumsi dan kinerja memori

Kasus lain di mana mendeklarasikan lebar kolom dapat membuat perbedaan besar adalah jika tabel akan diproses menggunakan SSIS. Memori yang dialokasikan untuk kolom panjang variabel (non BLOB) ditetapkan untuk setiap baris dalam pohon eksekusi dan sesuai dengan panjang maksimum yang dinyatakan kolom yang dapat menyebabkan penggunaan buffer memori yang tidak efisien (contoh) . Sementara pengembang paket SSIS dapat menyatakan ukuran kolom yang lebih kecil daripada sumbernya, analisis ini paling baik dilakukan di awal dan diterapkan di sana.

Kembali ke mesin SQL Server itu sendiri kasus serupa adalah ketika menghitung hibah memori untuk mengalokasikan untuk SORToperasi SQL Server mengasumsikan bahwa varchar(x)kolom rata-rata akan mengkonsumsi x/2byte.

Jika sebagian besar varcharkolom Anda lebih penuh dari itu, ini dapat menyebabkan sortoperasi tumpah tempdb.

Dalam kasus Anda, jika varcharkolom Anda dideklarasikan sebagai 8000byte tetapi sebenarnya memiliki konten yang jauh lebih sedikit dari itu, kueri Anda akan dialokasikan memori yang tidak diperlukan yang jelas tidak efisien dan dapat menyebabkan menunggu pemberian memori.

Ini tercakup dalam Bagian 2 dari SQL Workshops Webcast 1 yang dapat diunduh dari sini atau lihat di bawah.

use tempdb;

CREATE TABLE T(
id INT IDENTITY(1,1) PRIMARY KEY,
number int,
name8000 VARCHAR(8000),
name500 VARCHAR(500))

INSERT INTO  T 
(number,name8000,name500)
SELECT number, name, name /*<--Same contents in both cols*/
FROM master..spt_values

SELECT id,name500
FROM T
ORDER BY number

Screenshot

SELECT id,name8000
FROM T
ORDER BY number

Screenshot

Martin Smith
sumber
1
jadi, jika hampir semua nilai saya adalah 3 atau 4 karakter, tidak dapat melebihi 4 karakter, dan saya ingin menghindari "operasi pengurutan tumpah ke tempdb", saya akan mendeklarasikan kolom saya VARCHAR (8) dan menggunakan batasan PERIKSA untuk memaksakan kolom itu lebar tidak boleh melebihi 4 karakter. Bagaimana menurut anda?
AK
12
@AlexKuznetsov - Untuk situasi itu saya akan menyatakannya char(4)karena ada 2 byte overhead per kolom variabel.
Martin Smith
9

Terlepas dari praktik terbaik (jawaban BBlake)

  • Anda mendapatkan peringatan tentang ukuran baris maksimum (8060) byte dan lebar indeks (900 byte) dengan DDL
  • DML akan mati jika melebihi batas tersebut
  • ANSI PADDING ON adalah default sehingga Anda bisa menyimpan seluruh whitespace
gbn
sumber
38
Hanya untuk memperjelas tentang ANSI PADDING ON: saat menggunakan nvarchardan varcharmengetik, ini hanya berarti bahwa spasi tambahan dipertahankan setelah penyisipan - bukan karena nilainya ditambah dengan spasi untuk ukuran kolom, seperti di chardan nchar.
Ben M
9

Ada beberapa kerugian dari kolom besar yang agak kurang jelas dan mungkin Anda ketahui nanti:

  • Semua kolom yang Anda gunakan dalam INDEX - tidak boleh lebih dari 900 byte
  • Semua kolom dalam klausa ORDER BY tidak boleh melebihi 8.060 byte. Ini agak sulit dipahami karena ini hanya berlaku untuk beberapa kolom. Lihat Batas ukuran baris SQL 2008 R2 terlampaui untuk detailnya)
  • Jika ukuran baris total melebihi 8.060 byte, Anda mendapatkan " tumpahan halaman " untuk baris itu. Hal ini mungkin memengaruhi kinerja (Halaman adalah unit alokasi di SQLServer dan diperbaiki pada 8000 byte + beberapa overhead. Melebihi ini tidak akan terlalu berat, tetapi perlu diperhatikan dan Anda harus mencoba menghindarinya jika Anda bisa dengan mudah)
  • Banyak struktur data internal lainnya, buffer, dan yang paling penting varaibles dan variabel tabel Anda sendiri semuanya perlu mencerminkan ukuran ini. Dengan ukuran yang berlebihan, alokasi memori yang berlebihan dapat mempengaruhi performa

Sebagai aturan umum, cobalah konservatif dengan lebar kolom. Jika menjadi masalah, Anda dapat dengan mudah mengembangkannya agar sesuai dengan kebutuhan. Jika Anda melihat masalah memori di kemudian hari, menyusutkan kolom yang lebar nanti mungkin menjadi tidak mungkin tanpa kehilangan data dan Anda tidak akan tahu harus mulai dari mana.

Dalam contoh nama bisnis Anda, pikirkan tentang di mana Anda bisa menampilkannya. Apakah memang ada ruang untuk 500 karakter ?? Jika tidak, tidak ada gunanya menyimpannya seperti itu. http://en.wikipedia.org/wiki/List_of_companies_of_the_United_States mencantumkan beberapa nama perusahaan dan jumlah maksimumnya sekitar 50 karakter. Jadi saya akan menggunakan 100 untuk kolom maks. Mungkin lebih seperti 80.

Oliver
sumber
2

Idealnya Anda ingin membuatnya lebih kecil dari itu, ke ukuran yang cukup panjang (500 tidak berukuran wajar) dan pastikan validasi klien menangkap saat data akan menjadi terlalu besar dan mengirim kesalahan yang berguna.

Sementara varchar tidak benar-benar akan mencadangkan ruang dalam database untuk ruang yang tidak terpakai, saya ingat versi SQL Server memiliki informasi tentang baris database yang lebih lebar dari beberapa jumlah byte (tidak ingat jumlah persisnya) dan benar-benar membuang data apa pun yang tidak sesuai. Sejumlah byte tersebut disediakan untuk hal-hal internal SQL Server.

Otis
sumber
benar, ini dulunya adalah masalah yang jauh lebih besar juga. Tapi saat ini, ruang sangat murah jadi menurut saya itu bukan masalah besar untuk dipertimbangkan, setidaknya dari sudut pandang saya.
BBlake
1
@jcollum: Dalam contoh Anda, 500 tampaknya tidak cukup untuk nama bisnis.
Otis
1
@BBlake: Terlepas dari biaya penyimpanan, jika SQL Server masih memiliki batasan ukuran baris, tidak masalah berapa banyak penyimpanan yang Anda miliki. Anda dapat menyimpan semuanya di textblob tetapi ada beberapa operasi SQL yang tidak dapat Anda lakukan pada blob yang dapat Anda lakukan di varchar.
Otis
2
@Otis: maksud saya adalah: tidak ada batasan sebenarnya pada ukuran nama bisnis. Kecuali ada hukum di suatu tempat. Jadi dalam hal ini saya akan membuat field varchar (8000) dan menyebutnya sehari. Pemikiran saya seperti ini: Batasan nyata? varchar (x). Tidak ada kendala nyata? varchar (8000).
jcollum
24
Saya pikir sekitar 30 karakter baik untuk nama kota, sampai saya melihat El Pueblo de Nuestra Señora la Reina de los Ángeles del Río de Porciúncula
StuartLC