Bir tablonun veri alanı neden ham verilerin boyutunun 4 katı kadar olabilir?


18

490 M satır ve 55 GB tablo alanı olan bir tablo var, bu yüzden satır başına yaklaşık 167 bayt. Tablonun üç sütunu vardır: a VARCHAR(100), a DATETIME2(0)ve a SMALLINT. VARCHARAlandaki metnin ortalama uzunluğu yaklaşık 21,5'tir, bu nedenle ham veri satır başına yaklaşık 32 bayt olmalıdır: için 22 + 2, için VARCHAR6 DATETIME2ve 16 bit tamsayı için 2.

Yukarıdaki alanın yalnızca veri olduğunu, endeks olmadığını unutmayın. Özellikler | altında bildirilen değeri kullanıyorum Depolama | Genel | Veri alanı.

Tabii ki biraz ek yük olmalı , ancak satır başına 135 bayt özellikle büyük bir tablo için çok fazla gibi görünüyor. Bu neden olabilir? Başka benzer çarpanlar gördü mü? Gerekli olan ekstra alan miktarını hangi faktörler etkileyebilir?

Karşılaştırma için, iki INTalan ve 1 M satır içeren bir tablo oluşturmaya çalıştım . Gereken veri alanı, 8 bayt ham veri ile karşılaştırıldığında, 16.4 MB: satır başına 17 bayt idi. Başka bir test tablosu ve gerçek tabloyla aynı metne sahip INTbir VARCHAR(100)nüfus tablosu, 28 artı biraz beklediğim satır başına 39 bayt (44 K satır) kullanır.

Yani üretim masasının yükü çok daha fazla. Bu daha büyük olduğu için mi? Dizin boyutlarının kabaca N * günlüğü (N) olmasını beklerdim, ancak gerçek verilerin neden doğrusal olmasının gerekli olduğunu neden anlamıyorum.

Herhangi bir işaretçi için şimdiden teşekkürler!

DÜZENLE:

Listelenen alanların tümü NOT NULL. Gerçek tablo, bu sırada, VARCHARsahada ve alanda kümelenmiş bir PK'ya sahiptir DATETIME2. İki test için birincisi INT(kümelenmiş) PK idi.

Önemli ise: tablo ping sonuçlarının bir kaydıdır. Alanlar URL, ping tarihi / saati ve milisaniye cinsinden gecikmedir. Veriler sürekli olarak eklenir ve asla güncellenmez, ancak veriler URL başına saatte yalnızca birkaç kayda indirgemek için periyodik olarak silinir.

DÜZENLE:

Çok ilginç bir cevap burada önerir, çok okuma ve yazma ile bir dizin için, yeniden inşa yararlı olmayabilir. Benim durumumda, tüketilen alan bir endişe kaynağıdır, ancak yazma performansı daha önemliyse, gevşek endekslerle daha iyi olabilir.

Yanıtlar:


11

Orijinal soru hakkındaki yorumlardan sonra, bu durumda kayıp alan, büyük parçalanmaya yol açan kümelenmiş anahtar seçiminden kaynaklanıyor gibi görünüyor.

Bu durumlarda daima parçalanma durumunu sys.dm_db_index_physical_stats üzerinden kontrol etmeye değer.

Düzenleme: Yorumlardaki güncellemeyi takiben

Ortalama sayfa yoğunluğu (kümelenmiş dizinin yeniden oluşturulmasından önce)% 24'tür ve orijinal soruya mükemmel şekilde uyar. Sayfalar sadece 1/4 doluydu, bu nedenle toplam boyut ham veri boyutunun 4 katı idi.


7

Disk üzerindeki yapıların ek yükü vardır:

  • satır başlığı
  • boş bitmap + işaretçisi
  • değişken uzunluklu sütun ofsetleri
  • satır sürüm işaretçileri (isteğe bağlı)
  • ...

2 x 4 bayt int sütunu alarak,

  • 4 bayt satır başlığı
  • NULL bitmap'e 2 bayt işaretçi
  • 2 int sütun için 8 bayt
  • 3 bayt NULL bitmap

Vay 17 bayt!

Orijinaliniz gibi daha fazla yüke sahip ikinci test tablonuz için de aynısını yapabilirsiniz:

  • Değişken uzunlukta sütunların sayısı için 2 bayt
  • Değişken uzunluk sütunu başına 2 bayt

Neden fark var? Ayrıca (bunlara bağlantı vermeyeceğim)

  • dizinleri birleştirmek için hiç yeniden oluşturdunuz mu?
  • siler alan geri kazanmaz
  • ortasına yerleştirirseniz veri sayfaları bölünür
  • güncellemeler ileri işaretlere neden olabilir (boşluk bırakır)
  • satır taşması
  • dizin yeniden oluşturma veya DBCC CLEANTABLE olmadan varchar sütun kaldırıldı
  • öbek veya tablo (öbek kümelenmiş dizin yok = kayıtlar her tarafa dağılmış)
  • RCSI yalıtım seviyesi (satır başına ekstra 14 bayt)
  • varchar içinde sondaki boşluklar (SET ANSI_PADDING varsayılan olarak AÇIK'tır). LEN yerine checl için DATALENGTH kullanın
  • Sp_spaceused ile çalıştır @updateusage = 'true'
  • ...

Şuna bakın: SQL Server: Bir 8 KB sayfayı dolduran bir tablo nasıl oluşturulur?

SO'dan:


2x4 bayt int sütun örneği% 100 doğru değil. 4 baytlık satır başlığınız olacaktır (sabit uzunluklu veri boyutu için 2 durum baytı ve 2 bayt). Ardından veriler için 2x4 baytınız olacak. Sütun sayısı için iki bayt ve boş bitmap için tek bir bayt, 17 değil toplam 15 bayt kayıt uzunluğu verir.
Mark S. Rasmussen

@Mark S. Rasmussen: "Sabit uzunluklu veri boyutu için 2 bayt" nereden alınır? MSDN? Ve boş bitmap her zaman 3 bayttır: sqlskills.com/blogs/paul/post/… + msdn.microsoft.com/en-us/library/ms178085%28v=sql.90%29.aspx
gbn

Vay, harika detay! VARCHARYukarıdaki tahminimde s'nin uzunluk alanını açıkladım , ancak sütun sayısı için değil. Bu tabloda NULLable alanı yok (bundan bahsetmiş olmalıydım), yine de onlar için bayt ayırıyor mu?
Tüm

Endekslerin yeniden oluşturulması, gerekli alanın veri kısmını etkiler mi ? Belki de kümelenmiş dizini yeniden oluşturmak. Ekler, ortada çok olur, ancak durdurulacak kümelenme alanlarının sırasını değiştirirsem. Geri kalanların çoğu bu durumda uygulanmamalıdır, ancak genel durum için harika bir referanstır. Bağlantılarınızı kontrol edeceğim. İyi şeyler!
Tüm Ticaretten Jon

1
@gbn Sabit uzunluklu veri boyutu için 2 bayt, bahsettiğiniz 4 baytlık satır başlığının bir parçasıdır. Bu, sabit veri uzunluğu bölümünün sonuna / sütun sayısı / boş bitmap'in başına işaret eden işaretçidir. NULL bitmap her zaman üç bayt değildir . Sütun sayısını eklerseniz, en az üç bayt olacaktır, ancak daha fazla olabilir - Açıklamamda bitmap ve sütun sayısını böldüm. Ayrıca, NULL bitmap her zaman mevcut değildir , ancak bu durumda olacaktır.
Mark S. Rasmussen

5

Veri türleri zaman içinde değişti mi? Değişken uzunlukta sütunlar kaldırıldı mı? Dizinler sık ​​sık birleştirildi, ancak yeniden oluşturulmadı mı? Çok sayıda satır silindi veya çok sayıda değişken uzunlukta sütun önemli ölçüde güncellendi mi? Burada iyi bir tartışma var .


Bir veri türünü değiştirmediğimden veya bir alanı kaldırdığımdan% 97 eminim. Eğer yapsaydım, tablonun çok az sayıda satırı olduğunda çok erken olurdu. Silme veya güncelleme yoktur, veriler yalnızca eklenir.
Tüm Ticaretten Jon

Düzeltme: Orada olan siler ve biraz. Tabloda net bir büyüme var, bu yüzden bu alanın hızla yeniden kullanılacağını hayal ediyorum.
Tüm Ticaretten Jon

Birçok silme işlemi ile veriler yeniden kullanılabilir veya kullanılmayabilir. Tablonun kümeleme anahtarı nedir? Uçlar tablonun ortasında mı yoksa sonunda mı?
mrdenny

Kümelenmiş anahtar, VARCHARve DATETIME2alanlarındaki bu sırayla bileşiktir . Uçlar ilk alan için eşit olarak dağıtılacaktır. İkinci alan için, yeni değerler ve her zaman mevcut olanlardan daha büyük olacaktır.
Tüm Ticaretten Jon
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.