SQL Server 2005'te, açıkça bir uzunluk belirtmek yerine tüm karakter alanlarını nvarchar (MAX) yapmanın herhangi bir dezavantajı var mı, örneğin nvarchar (255)? (Alan uzunluğunu veritabanı düzeyinde sınırlayamayacağınız aşikar olanın dışında)
SQL Server 2005'te, açıkça bir uzunluk belirtmek yerine tüm karakter alanlarını nvarchar (MAX) yapmanın herhangi bir dezavantajı var mı, örneğin nvarchar (255)? (Alan uzunluğunu veritabanı düzeyinde sınırlayamayacağınız aşikar olanın dışında)
Yanıtlar:
Aynı soru MSDN Forumları'nda da soruldu:
Orijinal gönderiden (daha fazla bilgi var):
Verileri bir VARCHAR (N) sütununa depoladığınızda, değerler fiziksel olarak aynı şekilde saklanır. Ancak bir VARCHAR (MAX) sütununa kaydettiğinizde, ekranın arkasında veriler METİN değeri olarak işlenir. Bu nedenle, bir VARCHAR (MAX) değeriyle uğraşırken bazı ek işlemlere ihtiyaç vardır. (yalnızca boyut 8000'i aşarsa)
VARCHAR (MAX) veya NVARCHAR (MAX) 'büyük değer türü' olarak kabul edilir. Büyük değer türleri genellikle 'sıra dışı' olarak depolanır. Bu, veri satırının "büyük değer" in depolandığı başka bir konuma işaretçi olacağı anlamına gelir ...
N/VARCHAR(MAX)
çünkü "sadece 8000'i aştığında ek işleme var". Böylece, maliyeti sadece gerektiğinde alırsınız ve veritabanınız daha az kısıtlayıcıdır . Bunu yanlış mı okuyorum? Eğer hemen her zaman isteyeyim gibi görünüyor N/VARCHAR(MAX)
ziyade N/VARCHAR(1-8000)
...
sp_tableoptions
: msdn.microsoft.com/en-us/library/ms173530.aspx . VARCHAR (255) türleri de sıra dışına itilebilir, belirtilen 'genel gider' MAX ve 255 için tam olarak aynı olabilir. MAX türlerini TEXT türleriyle, farklı olduklarında (manipüle etmek için tamamen farklı API, farklı depolama vb). Gerçek farklardan bahsetmez: endeks yok, MAX türlerinde çevrimiçi işlem yok
Bu adil bir soru ve bariz olandan ayrı olarak ifade etti…
Dezavantajları şunları içerebilir:
Performans sonuçları Sorgu iyileştirici, en etkili uygulama planını belirlemek için alan boyutunu kullanır
"1. Veritabanındaki alan tahsisi uzar ve veritabanının sayfaları esnektir. Bu nedenle, güncellemeyi kullanarak alana bilgi eklerken, yeni veriler bir öncekinden daha uzunsa, bir işaretçi oluşturmak zorunda kalacaktır. Bu veritabanı dosyaları parçalanmak = dizinden silmek, güncellemek ve eklemek için neredeyse her şeyde daha düşük performans. " http://sqlblogcasts.com/blogs/simons/archive/2006/02/28/Why-use-anything-but-varchar_2800_max_2900_.aspx
Entegrasyon sonuçları - diğer sistemlerin veritabanınızla nasıl entegre edileceğini bilmesi zor Verilerin öngörülemeyen büyümesi Olası güvenlik sorunları, örneğin tüm disk alanını kaplayarak bir sistemi çökertebilirsiniz
Burada iyi bir makale var: http://searchsqlserver.techtarget.com/tip/1,289483,sid87_gci1098157,00.html
varchar(max)
.
Kabul edilen cevapta verilen bağlantıya göre:
Bir nvarchar(MAX)
alanda saklanan 100 karakter, bir nvarchar(100)
alandaki 100 karakterden farklı olarak saklanmaz - veriler satır içi olarak saklanır ve 'satır dışında' veri okuma ve yazma yükünüz olmaz. Yani endişelenmenize gerek yok.
Boyut 4000'den büyükse, veriler otomatik olarak 'sıra dışı' olarak saklanır, bu da istersiniz. Yani endişelenme de yok.
Ancak...
nvarchar(MAX)
sütunda dizin oluşturamazsınız . Tam metin dizine ekleme özelliğini kullanabilirsiniz, ancak sorgu performansını artırmak için sütunda dizin oluşturamazsınız. Benim için bu anlaşmayı kapatıyor ... her zaman nvarchar (MAX) kullanmak kesinlikle bir dezavantaj.Sonuç:
Tüm veritabanınız boyunca dizinlenebilen ve alan ve erişim süresini boşa harcamayan bir tür "evrensel dize uzunluğu" istiyorsanız, kullanabilirsiniz nvarchar(4000)
.
nvarchar(max)
her zaman kullanmıyorsunuz - string
C # gibi ? - ama nokta 3) (indeks sorunu) cevap veriyor.
nvarchar(4000)
Bazen veri türünün içindeki veriler üzerinde bir anlam ifade etmesini istersiniz.
Diyelim ki gerçekten 20 karakterden uzun olmaması gereken bir sütununuz var. Bu sütunu VARCHAR (MAX) olarak tanımlarsanız, bazı haydut uygulamaları uzun bir dize ekleyebilir ve bunu asla bilemezsiniz veya engellemezsiniz.
Uygulamanız bu dizeyi bir daha kullandığında, dizenin uzunluğunun temsil ettiği etki alanı için mütevazı ve makul olduğu varsayımı altında, öngörülemeyen ve kafa karıştırıcı bir sonuç elde edersiniz.
Bazı makaleleri kontrol ettim ve kullanışlı test komut dosyası buldum: http://www.sqlservercentral.com/Forums/Topic1480639-1292-1.aspx NVARCHAR (10) vs NVARCHAR (4000) vs NVARCHAR (MAX) ) ve belirtilen sayıları kullanırken hız farkını bulamıyorum, ancak MAX kullanırken. Kendiniz test edebilirsiniz. Umarım bu yardım.
SET NOCOUNT ON;
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(10)
DECLARE @SomeString NVARCHAR(10),
@StartTime DATETIME;
--=====
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='10', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(4000)
DECLARE @SomeString NVARCHAR(4000),
@StartTime DATETIME;
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='4000', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
--===== Test Variable Assignment 1,000,000 times using NVARCHAR(MAX)
DECLARE @SomeString NVARCHAR(MAX),
@StartTime DATETIME;
SELECT @startTime = GETDATE();
SELECT TOP 1000000
@SomeString = 'ABC'
FROM master.sys.all_columns ac1,
master.sys.all_columns ac2;
SELECT testTime='MAX', Duration = DATEDIFF(ms,@StartTime,GETDATE());
GO
Bunu başka bir güvenlik seviyesi olarak düşünün. Tablonuzu yabancı anahtar ilişkileri olmadan - tamamen geçerli - tasarlayabilir ve ilişkili işlerin tamamen iş katmanında bulunmasını sağlayabilirsiniz. Bununla birlikte, yabancı anahtarlar iyi tasarım uygulamaları olarak kabul edilir, çünkü iş katmanında bir şeylerin karışması durumunda başka bir kısıtlama seviyesi eklerler. Aynı durum alan boyutu sınırlaması için de geçerlidir ve varchar MAX kullanmamak için de geçerlidir.
Maks veya metin alanlarını kullanmamanın bir nedeni, çevrimiçi dizin yeniden oluşturma işlemleri gerçekleştirememenizdir; örneğin, SQL Server Enterprise Edition ile bile ONLINE İLE REBUILD = ON.
Tek sorun buldum biz SQL Server 2005 uygulamalarımızı geliştirmek ve bir durumda, biz SQL Server 2000 Sadece öğrendim desteklemek zorunda olmasıydı zor yoldan SQL Server 2000 varchar veya MAX seçenek gibi değil o nvarchar.
Alanın 5 ila 10 karakter arasında bir aralıkta olacağını bildiğinizde kötü fikir. Sanırım max'ı sadece uzunluğun ne olacağından emin olmasaydım kullanırdım. Örneğin, bir telefon numarası asla belirli sayıda karakterden fazla olamaz.
Dürüst olmak gerekirse, tablonuzdaki her alan için yaklaşık uzunluk gereksinimleri hakkında belirsiz olduğunuzu söyleyebilir misiniz?
Ne demek istediğini anladım - kesinlikle varchar (max) kullanmayı düşüneceğim bazı alanlar var.
İlginçtir ki MSDN belgeleri oldukça iyi özetliyor:
Sütun veri girişlerinin boyutları önemli ölçüde değiştiğinde varchar kullanın. Sütun veri girişlerinin boyutları önemli ölçüde değiştiğinde ve boyut 8.000 baytı aştığında varchar (max) kullanın.
Veritabanının işi, verileri işletme tarafından kullanılabilmesi için depolamaktır. Bu verileri faydalı kılmanın bir parçası, anlamlı olmasını sağlamaktır. Birisinin ilk adı için sınırsız sayıda karakter girmesine izin vermek anlamlı veriler sağlamaz.
Bu kısıtlamaları iş katmanına eklemek iyi bir fikirdir, ancak bu veritabanının bozulmadan kalmasını sağlamaz. Veri kurallarının ihlal edilmediğini garanti etmenin tek yolu, bunları veritabanında mümkün olan en düşük düzeyde uygulamaktır.
Bir sorun, SQL Server'ın birden çok sürümü ile çalışmak zorundaysanız, MAX her zaman çalışmaz olmasıdır. Bu nedenle, eski DB'ler veya birden çok sürüm içeren başka bir durumla çalışıyorsanız, çok dikkatli olmanız daha iyi olur.
Yukarıda belirtildiği gibi, öncelikle depolama ve performans arasında bir ödünleşmedir. En azından çoğu durumda.
Bununla birlikte, n / varchar (n) yerine n / varchar (Max) seçerken dikkate alınması gereken en az bir faktör daha vardır. Veriler dizine eklenecek mi (örneğin, bir soyadı gibi)? MAX tanımı LOB olarak kabul edildiğinden, MAX olarak tanımlanan hiçbir şey indeksleme için kullanılamaz. ve bir dizin olmadan, verileri bir WHERE yan tümcesinde yüklem olarak içeren herhangi bir arama, veri aramaları için alabileceğiniz en kötü performans olan Tam Tablo taramasına zorlanacaktır.
1) SQL sunucusunun nvarchar (max) vs nvarchar (n) ile uğraşırken daha fazla kaynak kullanması gerekir (ayrılan bellek ve işlemci zamanı), burada n alana özel bir sayıdır.
2) Bu performans açısından ne anlama geliyor?
SQL Server 2005'te, 15 nvarchar (max) sütun içeren bir tablodan 13.000 satır veri sorguladım. Sorguları tekrar tekrar zamanladım ve sonra sütunları nvarchar (255) veya daha azına değiştirdim.
Optimizasyondan önceki sorguların ortalaması 2.0858 saniyedir. Değişiklikten sonraki sorgular ortalama 1,90 saniyede geri döndü. Bu temel select * sorgusunda yaklaşık 184 milisaniyelik bir iyileşme idi. Bu% 8.8'lik bir gelişme.
3) Sonuçlarım, performans farkı olduğunu belirten birkaç makaleyle uyumlu. Veritabanınıza ve sorgunuza bağlı olarak, iyileştirme yüzdesi değişebilir. Çok sayıda eşzamanlı kullanıcınız veya çok fazla kaydınız yoksa, performans farkı sizin için sorun olmayacaktır. Ancak, daha fazla kayıt ve eşzamanlı kullanıcı arttıkça performans farkı da artacaktır.
Ben dizeleri yastıklı ve varchar (max) çıktı koymak bir udf vardı. Ayarlanan sütun için uygun boyuta geri döndürmek yerine doğrudan kullanıldıysa, performans çok zayıftı. Dize daha küçük bir boyuta yeniden dökmek için udf'un tüm arayanlarına güvenmek yerine udf'u keyfi bir uzunluğa koyarak büyük bir notla bitirdim.
Bir satırdaki tüm veriler (tüm sütunlar için) hiçbir zaman makul olarak 8000 veya daha az karakter almazsa, veri katmanındaki tasarım bunu zorlamalıdır.
Veritabanı motoru her şeyi blob depolama dışında tutmak çok daha verimlidir. Daha küçük bir satırı daha iyi kısıtlayabilirsiniz. Bir sayfada ne kadar çok satır tıklarsanız o kadar iyi olur. Veritabanı daha az sayfaya erişmesi gerektiğinde daha iyi performans gösterir.
Testlerim, seçim yaparken farklılıklar olduğunu gösterdi.
CREATE TABLE t4000 (a NVARCHAR(4000) NULL);
CREATE TABLE tmax (a NVARCHAR(MAX) NULL);
DECLARE @abc4 NVARCHAR(4000) = N'ABC';
INSERT INTO t4000
SELECT TOP 1000000 @abc4
FROM
master.sys.all_columns ac1,
master.sys.all_columns ac2;
DECLARE @abc NVARCHAR(MAX) = N'ABC';
INSERT INTO tmax
SELECT TOP 1000000 @abc
FROM
master.sys.all_columns ac1,
master.sys.all_columns ac2;
SET STATISTICS TIME ON;
SET STATISTICS IO ON;
SELECT * FROM dbo.t4000;
SELECT * FROM dbo.tmax;
İlginç bağlantı: TEXT'i kullanırken neden VARCHAR kullanıyorsunuz?
PostgreSQL ve MySQL ile ilgili, bu nedenle performans analizi farklı, ancak "açıklık" mantığı hala geçerli: Neden kendinizi her zaman küçük bir yüzdeyle ilgili bir şey için endişelenmeye zorluyorsunuz? Bir değişkene bir e-posta adresi kaydettiyseniz, '80 karakterle sınırlı' bir dize değil, bir 'dize' kullanırsınız.
Görebildiğim ana dezavantaj, diyelim ki buna sahipsin:
Hangisi size arayüz için gerekli veriler hakkında en fazla bilgiyi verir?
Bu
CREATE TABLE [dbo].[BusData](
[ID] [int] IDENTITY(1,1) NOT NULL,
[RecordId] [nvarchar](MAX) NULL,
[CompanyName] [nvarchar](MAX) NOT NULL,
[FirstName] [nvarchar](MAX) NOT NULL,
[LastName] [nvarchar](MAX) NOT NULL,
[ADDRESS] [nvarchar](MAX) NOT NULL,
[CITY] [nvarchar](MAX) NOT NULL,
[County] [nvarchar](MAX) NOT NULL,
[STATE] [nvarchar](MAX) NOT NULL,
[ZIP] [nvarchar](MAX) NOT NULL,
[PHONE] [nvarchar](MAX) NOT NULL,
[COUNTRY] [nvarchar](MAX) NOT NULL,
[NPA] [nvarchar](MAX) NULL,
[NXX] [nvarchar](MAX) NULL,
[XXXX] [nvarchar](MAX) NULL,
[CurrentRecord] [nvarchar](MAX) NULL,
[TotalCount] [nvarchar](MAX) NULL,
[Status] [int] NOT NULL,
[ChangeDate] [datetime] NOT NULL
) ON [PRIMARY]
Veya bu?
CREATE TABLE [dbo].[BusData](
[ID] [int] IDENTITY(1,1) NOT NULL,
[RecordId] [nvarchar](50) NULL,
[CompanyName] [nvarchar](50) NOT NULL,
[FirstName] [nvarchar](50) NOT NULL,
[LastName] [nvarchar](50) NOT NULL,
[ADDRESS] [nvarchar](50) NOT NULL,
[CITY] [nvarchar](50) NOT NULL,
[County] [nvarchar](50) NOT NULL,
[STATE] [nvarchar](2) NOT NULL,
[ZIP] [nvarchar](16) NOT NULL,
[PHONE] [nvarchar](18) NOT NULL,
[COUNTRY] [nvarchar](50) NOT NULL,
[NPA] [nvarchar](3) NULL,
[NXX] [nvarchar](3) NULL,
[XXXX] [nvarchar](4) NULL,
[CurrentRecord] [nvarchar](50) NULL,
[TotalCount] [nvarchar](50) NULL,
[Status] [int] NOT NULL,
[ChangeDate] [datetime] NOT NULL
) ON [PRIMARY]
Bir dezavantajı, öngörülemeyen bir değişken etrafında tasarlanacak olmanız ve satırlar, sayfalar ve uzantılardan aşamalı olarak oluşan dahili SQL Server veri yapısından yararlanmak yerine muhtemelen yok sayacak olmanızdır.
Bu da C'deki veri yapısı hizalaması hakkında düşünmemi sağlıyor ve hizalamanın farkında olmanın genellikle İyi Bir Şey (TM) olduğu düşünülüyor. Benzer fikir, farklı bağlam.
Sayfalar ve Uzantılar için MSDN sayfası
Satır Taşması Verileri için MSDN sayfası
önce bunu düşündüm ama sonra tekrar düşündüm. Performans sonuçları vardır, ancak aynı şekilde alanların gerçekte ne büyüklükte olduğu hakkında bir fikir sahibi olmak için bir dokümantasyon görevi görür. Ve bu veritabanı daha büyük bir ekosistemde oturduğunda zorlar. Kanımca anahtar, izin vericidir, ancak sadece akılda kalmaktır.
tamam, iş ve veri katmanı mantığı konusundaki hislerim burada. DB'niz, iş mantığını paylaşan sistemler arasında paylaşılan bir kaynak ise, elbette bu mantığı uygulamak için doğal bir yer gibi görünüyor, ancak bunu yapmanın EN İYİ yolu değil, EN İYİ yol bir API sağlamaktır, bu izin verir test edilecek etkileşim ve iş mantığını ait olduğu yerde tutar, sistemleri ayrıştırır, bir sistem içindeki katmanlarınızı ayırır. Ancak veritabanınızın sadece bir uygulamaya hizmet vermesi gerekiyorsa, ÇEVİK düşünmeye başlayalım, şimdi ne var? Şimdilik tasarım. Bu tür bir erişim gerekiyorsa ve ne zaman gerekiyorsa, bu verilere bir API sağlayın.
Açıkçası, bu sadece ideal, eğer mevcut bir sistemle çalışıyorsanız, muhtemelen en azından kısa vadede farklı bir şekilde yapmanız gerekecek.
Bu, bir performans sorununa neden olur, ancak veritabanınız küçükse hiçbir zaman gerçek sorunlara neden olmayabilir. Her kayıt sabit sürücüde daha fazla yer kaplar ve aynı anda çok sayıda kayıtta arama yapıyorsanız veritabanının diskin daha fazla bölümünü okuması gerekir. Örneğin, küçük bir kayıt bir sektöre 50 sığabilir ve büyük bir kayıt 5'e sığabilir. Büyük kaydı kullanarak diskten 10 kat daha fazla veri okumanız gerekir.
nvarchar(max)
sütunda saklanan 100 uzunluklu bir dize, bir sütunda olduğundan daha fazla disk alanı gerektirmez nvarchar(100)
.