Bir varchar sütununun veritabanı dosyasındaki boyutunu azaltmanın etkisi nedir?


15

Veritabanımızda, (veya maks'den çok daha küçük bir şeyin) yeterli olacağı VARCHAR(MAX)sütunlara sahip bir dizi tablo var VARCHAR(500). Doğal olarak bunları temizlemek ve boyutları daha makul seviyelere indirmek istiyorum. Bunu nasıl yapacağımı anlıyorum: sorum, bu sütunları değiştirmenin diskteki sayfalara ve sabitlere ne yapacağıdır? (Bir sütunu büyüttüğünüzde neler olduğu hakkında çok fazla bilgi var, ancak bir sütunu küçülttüğünüzde neler olduğu hakkında bilgi bulmakta zorlanıyor.)

Bazı tablolar çok küçük bir satır sayısına sahiptir, bu yüzden değişikliğin maliyeti hakkında endişelenmiyorum, ancak bazıları oldukça büyük ve potansiyel olarak yeniden düzenlenmesinden ve çok fazla engelleme / kesintiye neden olmasından endişe duyuyorum. Pratik anlamda, sadece bir bakım penceresi tahmin etmenin bir yolunu istiyorum. Genel olarak, veritabanı motorunun bu durumda nasıl davrandığını daha iyi anlamak istiyorum.

Şimdiden teşekkürler!

DÜZENLE:

Baktığım 20 tablo var, ancak bunların yarısının 1.000'den fazla satır sayısı var. En büyüğünün neredeyse bir milyon satırı vardır. En kötü suçlu, 350.000 sıra ve seviyeye VARCHAR(MAX)kadar daralan dört sütunlu bir masa VARCHAR(500).

Yanıtlar:


12

İlk önce: Tabloda ne kadar veri var? Satır sayısı ve tablonun boyutu?

İkincisi: Bu tabloyu yedekleyip bir test sunucusuna geri yükleyebilir ve etkiyi görmek için alter deyimini çalıştırabilir misiniz (tablonun Üretim dışı bir sisteme sığmayacak kadar büyük olması nedeniyle mümkün olmadığı varsayılarak)? Her zaman çevremde test etmenin internetler arası tavsiyeden daha doğru olduğunu görüyorum, çünkü sadece bu faktörlerin sonucu etkileyebileceğini bilmemesi nedeniyle soruda sağlanamayan sonucu etkileyebilecek çeşitli faktörler vardır.

Üçüncüsü: artan değişken uzunlukta alanının boyutunu olan hiçbir gerçek veri böyle bir operasyon için değişen olacağından basit meta veri işlemi (eğer üzerinde 8060 bayt sınırı gitmez varsayarak). ANCAK, diğer taraftan, indirgeyici bir değişken uzunlukta alanının boyutunu, hatta, daha açıkçası işin daha kalacak bir şekilde değil tüm satırları tarayarak önce SQL Server bilmediği için basit bir meta veri değişimi, , yeni istenen boyutun geçerli olduğunu belirtir.

Dolayısıyla: Evet, bu masayı bir süre kilitleyecektir . Ne kadar zaman? İşte yeni yaptığım test:

Diğer bazı testlerden, tek bir INT NOT NULLalana ve 1 milyon sıraya sahip bir masam vardı . Bu testi yapmak için yeni bir tabloya kopyaladım:

SELECT *, CONVERT(NVARCHAR(MAX), NEWID()) AS [StringField]
INTO dbo.ResizeTest
FROM dbo.ClusteredUnique;

Bu şekilde, daha sonra değiştirebileceğim bir MAXalanın (sadece sahip olduğunuzu VARCHARve kullandığımı fark ettim NVARCHAR, ancak bu gördüğüm davranışı değiştirmemeliydim) sahip olmak için benzer bir senaryo ile başlıyordum 500. İçinde 500 karaktere kolayca sığabilen veriler var. Birkaç dakika sürdü.

Sonra koştum:

ALTER TABLE dbo.ResizeTest ALTER COLUMN [StringField] NVARCHAR(500) NULL;

Ve bu 11 dakikadan biraz fazla sürdü.

Testi tekrar tekrar çalıştırdım, bu sefer [ResizeTest]masayı bırakarak ve her ikisini NVARCHARde sadece VARCHARen azından bir elma ;-) gibi görünen bir şeyle karşılaştırdığımdan emin olmak için, sadece s olarak değiştiriyorum .

İlk tablo oluşturma işlemi 20 saniye sürerken ALTER TABLE2 dakika sürdü.

Bu nedenle, kesinti süresini tahmin etmek için, veri dosyasında ve / veya işlem günlüğünde vb. Herhangi bir otomatik büyüme işleminin olması gerekip gerekmediği disk G / Ç hızlarına bağlı olduğu için bunu yapmak gerçekten zordur. Muhtemelen ilk testimin değiştirilmesinin 11 dakika sürdüğünün büyük bir kısmı ve ikincisi, verilerin VARCHARyarısı boyutunda olsa bile NVARCHAR, sadece 2 dakika sürdü (yani dosyalar bu noktada önceden oluşturuldu). Ancak yine de, testimin en hızlı disk olmayan dizüstü bilgisayarımda çalıştığını, ancak aynı zamanda sadece 1 milyon satır 2 küçük sütunun (satır başına 22 veya bayt) olduğunu unutmayın.

Ve veri sayfalarına ne yapacağını sorduğunuzdan, işte cevabınız. sp_spaceusedMasayı oluşturduktan sonra, yaptıktan sonra ALTER COLUMNve yaptıktan sonra yaptım ALTER TABLE dbo.ResizeTest REBUILD;. Sonuçlar (aşağıdaki sayılar VARCHARilk testi değil, ikinci testi temel alır NVARCHAR):

After initial table creation:        526,344 KB
After ALTER COLUMN VARCHAR(500):   1,031,688 KB  <--- !! Yikes!!
After ALTER REBUILD:                 526,472 KB

İşlemi mümkün olan en kısa süre içinde tutmaya ihtiyaç duyduğunuzdan endişe ediyorsanız, aşağıdakileri yaptığım hakkında yazdığım bir makaleye göz atın : 100 Milyon Satır (veya daha fazla) Tabloyu Saniyede Yeniden Yapılandırın. SRSLY! (ücretsiz kayıt gereklidir).


2
Bu yüzden en kötü tabloyu yerel örneğime kopyaladım (yani daha yavaş disk ve çekirdeklerin 1 / 3'ü). Ben ALTERarka arkaya, her sütun ed - her bir eylem, bir saniyeden daha az aldı. Yapıldıkları zaman, tablonun boyutu iki katına çıkmıştı, ancak bir kez REBUILD(ki ikinci bir işlemdi) yaptığımda , masa orijinal boyutuna geri döndü.
nateirvin

@nateirvin Bunu duymak güzel. ALTER TABLEHer sütunu tek bir vuruşta ayırarak ve her sütunu virgülle ayırarak işlemi hızlandırabilirsiniz . İşlem çok büyükse, tabloyu sütunların yarısının 2 ALTER ifadesine bölün. Tablonun ne kadar büyük olduğuna bağlı olarak, iki ALTER ifadesinin her biri arasında bir REBUILD bile yapabilirsiniz. Oynamak için bir şey. Ayrıca, işlemin büyük olasılıkla tabloya tüm erişimi engelleyecek bir şema kilidi alacağını unutmayın.
Solomon Rutzky

1
Her birini ALTERayrı ayrı yaptım, böylece her biri arasındaki boyut değişikliklerini izleyebildim, ama kesinlikle iyi biliyorum. Teşekkürler!
nateirvin

1

Alter deyimini çalıştırarak topladığımdan, masada başka bir işlem tarafından kilitlenmediği sürece çok uzun sürmemelidir. Gbn'ye göre bu sadece bir meta veri değişikliği: /programming/7261909/is-it-bad-to-use-alter-table-to-resize-a-varchar-column-to-a-larger -boyut

Ayrıca, nasıl depolandığına gelince, SQL Server varchar verilerini tüm sayfayı doldurana kadar 8k sayfada sakladı gibi görünüyor, bu noktada bir işaretçi ile değiştiriyor ve bir BLOB olarak saklıyor.

Uzunluğunu değiştirdiğinizde herhangi bir kayıt kesmeyeceğinizi varsayıyorum. Eğer öyleyse, maksimum olarak varchar (500) 'e dönüştürdüğünüz verilerin en fazla 502 bayt uzunluğunda ve bir işaretçisi olmamalıdır.

Yani, uzun lafın kısası, herhangi bir veriyi kesmediğiniz sürece çok fazla değişmemelidir.


5
Bu kesinlikle yanlış. Ben aşağı test etmeyeceğim, çünkü gerçekten test ettiniz (bazı milletlerden daha fazla, bunu yaptığınız için teşekkürler), ancak bunu ölçekli olarak test etmeniz gerekiyor. Bağlantı kurduğunuz cevap boyutu küçültmek değil, büyütmekti. Bunlar çok farklı iki operasyon.
Solomon Rutzky
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.