SQL varchar sütun uzunluğu için en iyi uygulamalar [kapalı]


290

Her zaman yeni bir SQL tablo kurmak veya varcharvarolan bir tabloya yeni bir sütun eklemek , bir şey merak ediyorum: en iyi değeri nedir length.

Diyelim ki nametür adında bir sütun var varchar. Yani, uzunluğu seçmek zorundasınız. 20 karakterden fazla bir isim düşünemiyorum ama asla bilemeyeceksin. Ama 20 kullanmak yerine, her zaman bir sonraki 2 ^ n numarasına yuvarlanırım. Bu durumda, uzunluk olarak 32'yi seçerdim. Bunu yapıyorum, çünkü bir bilgisayar bilimcisi açısından, bir sayı 2 ^ n evenbana diğer sayılardan daha fazla görünüyor ve sadece altındaki mimarinin bu sayıları diğerlerinden biraz daha iyi işleyebileceğini varsayıyorum.

Öte yandan, örneğin bir varchar sütunu oluşturmayı seçtiğinizde MSSQL sunucusu varsayılan uzunluk değerini 50 olarak ayarlar. Bu beni düşündürüyor. Neden 50? bu rastgele bir sayı mı yoksa ortalama sütun uzunluğuna mı dayanıyor, yoksa ne?

Farklı SQL sunucu uygulamalarının (MySQL, MSSQL, Postgres, ... gibi) farklı en iyi sütun uzunluğu değerlerine sahip olması da olabilir - veya muhtemelen de olabilir.

Yanıtlar:


238

Ben bildiğim hiçbir DBMS uzunluğu bir güç 2 olmayan bir uzunluktan daha iyi VARCHARbir 2^nperformans yapacak herhangi bir "optimizasyon" vardır max.

Bence erken SQL Server sürümleri aslında VARCHARbir daha yüksek maksimum uzunluğa sahip 255 farklı bir uzunluğu ile tedavi . Hala böyle olup olmadığını bilmiyorum.

Hemen hemen tüm DBMS için gereken gerçek depolama alanı, maxtanımladığınız uzunluk değil, yalnızca içine koyduğunuz karakter sayısı ile belirlenir . Bu nedenle, depolama açısından (ve büyük olasılıkla bir performans da), bir sütunu VARCHAR(100)veya olarak bildirmeniz fark etmez VARCHAR(500).

maxBir VARCHARsütun için sağlanan uzunluğu teknik / fiziksel bir şey yerine bir tür kısıtlama (veya iş kuralı) olarak görmelisiniz .

PostgreSQL için en iyi kurulum, textuzunluk sınırlaması olmadan kullanmak ve CHECK CONSTRAINTkarakter sayısını işinizin gerektirdiği şekilde sınırlamaktır.

Bu gereksinim değişirse, kontrol kısıtlamasını değiştirmek tabloyu değiştirmekten çok daha hızlıdır (çünkü tablonun yeniden yazılmasına gerek yoktur)

Aynı şey Oracle ve diğerleri için de uygulanabilir - Oracle'da olsa VARCHAR(4000)bunun yerine olurdu text.

SQL Server arasında VARCHAR(max)ve örneğin fiziksel bir depolama farkı olup olmadığını bilmiyorum VARCHAR(500). Ancak görünüşe göre, kullanırken varchar(max)karşılaştırıldığında bir performans etkisi var varchar(8000).

Bu bağlantıya bakın (Erwin Brandstetter tarafından yorum olarak gönderildi)

Düzenle 2013-09-22

Bigown'un yorumu ile ilgili:

Postgres versiyonları 9.2 önce kolon tanımına bir değişiklik (ben ilk cevap yazarken hangi mevcut değildi) did örneğin bkz, tüm tabloyu yeniden burada . 9.2'den beri bu artık geçerli değil ve hızlı bir test, 1.2 milyon sıralı bir tablo için sütun boyutunun artırılmasının sadece 0,5 saniye sürdüğünü doğruladı.

Oracle için bu büyük bir tablonun varcharsütununu değiştirmek için gereken süreye bakıldığında da doğru gibi görünüyor . Ama bunun için herhangi bir referans bulamadım.

MySQL için el kitabı " Çoğu durumda ALTER TABLEorijinal tablonun geçici bir kopyasını oluşturur " der . Ve kendi testlerim şunları ALTER TABLEdoğrular: Bir sütunun boyutunu artırmak için 1.2 milyon sıralı bir masada (Postgres ile yaptığım testte olduğu gibi) bir çalışma 1.5 dakika sürdü. MySQL ancak olabilir değil bir sütun karakter sayısını sınırlamak için bir denetim kısıtlaması kullanmak için "geçici" kullanın.

SQL Server Bu konuda net bir açıklama fakat boyutunu artırmak için yürütme zamanı bulamadık için varcharsütununa (yukarıdan tekrar 1,2 milyon satır tablo) belirtir hiçbir yeniden yazma gerçekleşir.

Düzenle 2017-01-24

SQL Server hakkında (en azından kısmen) yanılmışım gibi görünüyor. Aaron Bertrand'ın belirtilen bir a nvarcharveya varcharsütun uzunluğunun performans için büyük bir fark yarattığını gösteren bu cevaba bakın .


34
Aslında, böyle bir sütunun içine 1 karakter koymuş olsanız bile, VARCHAR (255) ve VARCHAR (500) arasında bir fark vardır. Satırın sonuna eklenen değer, saklanan verilerin gerçek uzunluğunu depolayan bir tamsayı olacaktır. VARCHAR (255) durumunda 1 bayt tam sayı olacaktır. VARCHAR (500) durumunda 2 bayt olacaktır. bu küçük bir fark, ama bunun farkında olmalı. Performansı nasıl etkileyebileceğine dair elimde veri yok, ancak araştırmaya değmeyecek kadar küçük olduğunu düşünüyorum.
NB

1
@NB: SQL Server'ın "sihirli" 255 değeri için bahsettiğim şey bu. Açıklama için teşekkürler.
a_horse_with_no_name

4
@NB Hangi RDBMS'den bahsediyorsunuz? SQL Server? Performans üzerinde bir etkisi vardır. [N] VARCHAR (maks.), [N] VARCHAR (n) 'den biraz daha yavaş performans gösterir. Kısa süre önce bu siteye yönlendirildim . Aynı şey bildiğim herkes için PostgreSQL için geçerli değil.
Erwin Brandstetter

@ErwinBrandstetter: Bağlantı için teşekkürler. Görünüşe varchar(max)göre muhtemelen Oracle'ınkine benziyorCLOB
a_horse_with_no_name 28:11

1
Varchar uzunluğunu değiştirme tabloyu yeniden yazmaz. Sadece kısıtlama uzunluğunu tam olarak KONTROL KONTROLÜ olarak tüm tabloya karşı kontrol edin. Uzunluğu artırırsanız yapacak bir şey kalmazsa, yalnızca sonraki ekleme veya güncellemeler daha büyük uzunluğu kabul eder. Uzunluğu azaltırsanız ve tüm satırlar yeni daha küçük kısıtlamayı geçerse, Pg sonraki eklemelerin veya güncellemelerin yalnızca yeni uzunluğu yazmasına izin vermenin yanı sıra başka bir işlem yapmaz.
Maniero

70

VARCHAR(255)ve VARCHAR(2)almak tam olarak diskte boşluk aynı miktarda! Bu yüzden bunu sınırlamanın tek nedeni, daha küçük olması için özel bir ihtiyacınız varsa. Aksi takdirde hepsini 255 yapın.

Özellikle, sıralama yaparken daha büyük sütun daha fazla yer kaplar, bu nedenle performans acıyorsa, endişelenmeniz ve daha küçük yapmanız gerekir. Ancak bu tablodan yalnızca 1 satır seçtiyseniz, bunları 255 olarak da yapabilirsiniz ve bunun bir önemi yoktur.

Bkz: MySQL için en uygun varchar boyutları nelerdir?


7
Neden hepsini yapmıyorsun VARCHAR(MAX)? Veritabanını modellerken yalnızca alan dikkate alınmaz. Modellemekte olduğunuz alan adı, veri türlerini ve boyutlarını desteklemelidir.
Oded

6
@Oded veya or VARCHAR(MAX)ile aynı değildir - varchar max bir tür veri tipidir . Demek istediğin, eğer "etki alanını modellemekte olduğunu" bilseydi, bu soruyu sormazdı. Açıkçası, verilerinin ne kadar büyük olacağını bilmiyor ve ona tam boyutta hiçbir şeyin zarar vermediğine güveniyorum. varchar(255)varchar(65535)text
Ariel

4
@Ariel: Dizinlerde dikkate alınması gereken sorunlar ve sınırlamalar da var. (a,b,c,d)Dört sütunun tümü olduğunda bir dizininiz olamaz VARCHAR(255).
ypercubeᵀᴹ

@ypercube Bu doğrudur, sütunlarınızın bir dizine ihtiyacı varsa, boyutlara daha dikkatli olmanız gerekir. Ancak çoğu sütunun bir dizine ihtiyacı yoktur, bu nedenle çoğu zaman endişelenmenize gerek yoktur.
Ariel

Sanırım char kullanmayı tercih ettiğim kesin değeri bilirsek. Bu arada hala tahmin ediyorsanız, varchar kullanıyorum ve dinamik bellek tahsisi olduğu için 255'i
tutuyorum

54

Ne zaman yeni bir SQL tablosu kurduğumda, 2 ^ n daha "eşit" olmakla aynı şekilde hissediyorum ... ama buradaki cevapları özetlemek gerekirse, sadece varchar (2 ^ n) tanımlayarak depolama alanı üzerinde önemli bir etkisi yoktur. hatta varchar (MAX).

Bununla birlikte, yüksek bir varchar () limiti belirlerken depolama ve performans üzerindeki olası etkileri hala beklemeniz gerekir. Örneğin, tam metin dizinlemeli ürün açıklamalarını tutmak için bir varchar (MAX) sütunu oluşturduğunuzu varsayalım. Açıklamaların% 99'u yalnızca 500 karakter uzunluğundaysa ve aniden bu açıklamaları wikipedia makaleleriyle değiştiren birisini alırsanız, beklenmedik önemli depolama ve performans hitleri fark edebilirsiniz.

Bill Karwin'den düşünülmesi gereken başka bir şey :

Olası bir performans etkisi vardır: MySQL'de geçici tablolar ve MEMORY tabloları, bir VARCHAR sütununu, sabit uzunluklu sütun olarak, maksimum uzunluğa kadar doldurulmuş olarak depolar. VARCHAR sütunlarını ihtiyacınız olan en büyük boyuttan çok daha büyük olarak tasarlarsanız, gerekenden daha fazla bellek tüketirsiniz. Bu önbellek verimliliğini, sıralama hızını vb. Etkiler.

Temel olarak, makul iş kısıtlamaları ve biraz daha büyük bir boyutta hata ile gel. @Oneday'ın belirttiği gibi, İngiltere'deki aile isimleri genellikle 1-35 karakter arasındadır. Varchar (64) yapmaya karar verirseniz, gerçekten hiçbir şeye zarar vermeyeceksiniz ... 666 karakter uzunluğunda olduğu söylenen bu adamın soyadını saklamadığınız sürece. Bu durumda, belki de varchar (1028) daha mantıklıdır.

Ve yararlı olması durumunda, varchar 2 ^ 5 ila 2 ^ 10 doldurulmuşsa şu şekilde görünebilir:

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

31

En iyi değer, temel etki alanında tanımlanan veriler için doğru değerdir.

Bazı alanlar VARCHAR(10)için, Nameözellik için doğrudur , çünkü diğer alanlar VARCHAR(255)için en iyi seçim olabilir.


15

A_horse_with_no_name cevabına ek olarak aşağıdakileri de bulabilirsiniz ...

bir sütunu VARCHAR (100) veya VACHAR (500) olarak bildirmeniz fark etmez.

-- 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

Uzunluk bayt (lar) ını ve nullable baytı unutma:

name varchar(100) not null 1 bayt (uzunluk) + 100 karaktere kadar (latin1)

name varchar(500) not null 2 bayt (uzunluk) + 500 karaktere kadar (latin1)

name varchar(65533) not null 2 bayt (uzunluk) + 65533 karaktere kadar (latin1)

name varchar(65532) 2 bayt (uzunluk) + 65532 karakter (latin1) + 1 boş bayt olur

Bu yardımcı olur umarım :)


MySQL kullanıyorsunuz ve soru MSSQL hakkında
Bogdan Mart


3

Son zamanlarda bunu kontrol etmedim, ancak geçmişte Oracle ile JDBC sürücüsünün sorgu yürütme sırasında sonuç kümesinin geri gelmesini sağlamak için bir yığın bellek ayıracağını biliyorum. Bellek yığınının boyutu sütun tanımlarına ve getirme boyutuna bağlıdır. Dolayısıyla varchar2 sütunlarının uzunluğu, ne kadar bellek ayrıldığını etkiler. Bu, yıllar önce benim için ciddi performans sorunlarına neden oldu, çünkü her zaman varchar2 (4000) (o sırada maksimum) kullandık ve çöp toplama bugün olduğundan çok daha az etkili oldu.


-2

Bir anlamda haklısınız, ancak 2 ^ 8 karakterden daha düşük bir değer yine de bir bayt veri olarak kaydedilecektir.

VARCHAR <255 olan herhangi bir şeyi bırakan temel karakteri aynı miktarda yer kaplıyorsa,

255, özellikle aşırı girdiyi azaltmak istemiyorsanız iyi bir temel tanımdır.


" Her ne kadar 2 ^ 8 karakterden daha düşük bir değer yine de veri baytı olarak kaydedilecektir " - yanlış. Veritabanı yalnızca VARCHAR türünde sağlanan sayıda karakteri depolar. Hiçbir boşluk, "kayıtlı" ayrılmış veya başlatılır ilan bir sütun.
a_horse_with_no_name
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.