Tam olarak neden bu davranışın gerçekleştiğini söyleyemem ama kaba kuvvet testi ile iyi bir davranış modeli geliştirdiğime inanıyorum. Aşağıdaki sonuçlar yalnızca tek bir sütuna veri yüklerken ve çok iyi dağıtılmış tamsayılarla geçerlidir.
Önce kullanarak CCI içine eklenen satır sayısını değiştirmeye çalıştım TOP
. ID % 16000
Tüm testler için kullandım . Aşağıda, sıkıştırılmış satır grubu segment boyutuna eklenen satırları karşılaştıran bir grafik bulunmaktadır:
Aşağıda ms cinsinden CPU zamanına eklenen satırların bir grafiği bulunmaktadır. X ekseninin farklı bir başlangıç noktasına sahip olduğuna dikkat edin:
Satır grubu segment boyutunun doğrusal bir oranda büyüdüğünü ve yaklaşık 1 M satıra kadar az miktarda CPU kullandığını görebiliriz. Bu noktada satır grubu boyutu önemli ölçüde azalır ve CPU kullanımı önemli ölçüde artar. Görünüşe göre bu sıkıştırma için CPU'da ağır bir bedel ödüyoruz.
1024000'den az satır eklerken CCI'da açık bir satır grubu buldum. Ancak, sıkıştırmayı kullanarak zorlama REORGANIZE
veya REBUILD
boyut üzerinde bir etkisi olmadı. Bir kenara, bir değişken kullandığımda TOP
açık bir satır grubu ile RECOMPILE
sona erdiğini, ancak kapalı bir satır grubu ile sona erdiğini ilginç buldum.
Daha sonra, satır sayısını aynı tutarken modül değerini değiştirerek test ettim. 102400 satır eklerken verilerin bir örneği:
╔═══════════╦═════════╦═══════════════╦═════════════╗
║ TOP_VALUE ║ MOD_NUM ║ SIZE_IN_BYTES ║ CPU_TIME_MS ║
╠═══════════╬═════════╬═══════════════╬═════════════╣
║ 102400 ║ 1580 ║ 13504 ║ 352 ║
║ 102400 ║ 1590 ║ 13584 ║ 316 ║
║ 102400 ║ 1600 ║ 13664 ║ 317 ║
║ 102400 ║ 1601 ║ 19624 ║ 270 ║
║ 102400 ║ 1602 ║ 25568 ║ 283 ║
║ 102400 ║ 1603 ║ 31520 ║ 286 ║
║ 102400 ║ 1604 ║ 37464 ║ 288 ║
║ 102400 ║ 1605 ║ 43408 ║ 273 ║
║ 102400 ║ 1606 ║ 49360 ║ 269 ║
║ 102400 ║ 1607 ║ 55304 ║ 265 ║
║ 102400 ║ 1608 ║ 61256 ║ 262 ║
║ 102400 ║ 1609 ║ 67200 ║ 255 ║
║ 102400 ║ 1610 ║ 73144 ║ 265 ║
║ 102400 ║ 1620 ║ 132616 ║ 132 ║
║ 102400 ║ 1621 ║ 138568 ║ 100 ║
║ 102400 ║ 1622 ║ 144512 ║ 91 ║
║ 102400 ║ 1623 ║ 150464 ║ 75 ║
║ 102400 ║ 1624 ║ 156408 ║ 60 ║
║ 102400 ║ 1625 ║ 162352 ║ 47 ║
║ 102400 ║ 1626 ║ 164712 ║ 41 ║
╚═══════════╩═════════╩═══════════════╩═════════════╝
1600 mod değerine kadar satır grubu segment boyutu, her ek 10 benzersiz değer için doğrusal olarak 80 bayt artar. İlginç bir tesadüfBIGINT
Geleneksel olarak 8 bayt alan ve segment boyutu, her bir benzersiz değer için 8 bayt artar. 1600 mod değerinden sonra segment boyutu stabil hale gelene kadar hızla artar.
Ayrıca, modül değerini aynı bırakıp eklenen satır sayısını değiştirirken verilere bakmak da yararlıdır:
╔═══════════╦═════════╦═══════════════╦═════════════╗
║ TOP_VALUE ║ MOD_NUM ║ SIZE_IN_BYTES ║ CPU_TIME_MS ║
╠═══════════╬═════════╬═══════════════╬═════════════╣
║ 300000 ║ 5000 ║ 600656 ║ 131 ║
║ 305000 ║ 5000 ║ 610664 ║ 124 ║
║ 310000 ║ 5000 ║ 620672 ║ 127 ║
║ 315000 ║ 5000 ║ 630680 ║ 132 ║
║ 320000 ║ 5000 ║ 40688 ║ 2344 ║
║ 325000 ║ 5000 ║ 40696 ║ 2577 ║
║ 330000 ║ 5000 ║ 40704 ║ 2589 ║
║ 335000 ║ 5000 ║ 40712 ║ 2673 ║
║ 340000 ║ 5000 ║ 40728 ║ 2715 ║
║ 345000 ║ 5000 ║ 40736 ║ 2744 ║
║ 350000 ║ 5000 ║ 40744 ║ 2157 ║
╚═══════════╩═════════╩═══════════════╩═════════════╝
Eklenen satır sayısı ~ ~ 64 * olduğunda, göreceli olarak düşük sıkıştırma (mod <= 65000 için satır başına 2 bayt) ve düşük, doğrusal CPU kullanımı gördüğümüz zamanki gibi görünüyor. Girilen satır sayısı> ~ 64 * olduğunda benzersiz değerlerin sayısı çok daha iyi sıkıştırma ve daha yüksek, hala doğrusal CPU kullanımı görüyoruz. İki durum arasında benim için modellenmesi kolay olmayan bir geçiş var, ancak grafikte görülebilir. Her benzersiz değer için tam olarak 64 satır eklerken maksimum CPU kullanımını gördüğümüz doğru görünmüyor. Bunun yerine, bir satır grubuna yalnızca en fazla 1048576 satır ekleyebiliriz ve benzersiz değer başına 64'ten fazla satır olduğunda çok daha yüksek CPU kullanımı ve sıkıştırması görürüz.
Aşağıda, eklenen satırların sayısı ve benzersiz satırların sayısı değiştikçe cpu zamanının nasıl değiştiğine dair bir kontur grafiği bulunmaktadır. Yukarıda açıklanan modelleri görebiliriz:
Aşağıda, segment tarafından kullanılan konturun bir alan grafiği verilmiştir. Belirli bir noktadan sonra yukarıda açıklandığı gibi çok daha iyi sıkıştırma görmeye başlarız:
Burada en az iki farklı sıkıştırma algoritması var gibi görünüyor. Yukarıdakiler göz önüne alındığında, 1048576 satır eklerken maksimum CPU kullanımını göreceğimiz mantıklıdır. Ayrıca, yaklaşık 16000 satır eklerken bu noktada en fazla CPU kullanımını gördüğümüz de anlamlıdır. 1048576/64 = 16384.
Birisinin analiz etmek istemesi durumunda tüm ham verilerimi buraya yükledim .
Paralel planlarda neler olduğunu anlatmaya değer. Bu davranışı sadece eşit dağıtılmış değerlerle gözlemledim. Paralel bir ekleme yaparken genellikle bir rastgelelik unsuru vardır ve dişler genellikle dengesizdir.
2097152 satırı hazırlama tablosuna yerleştirin:
DROP TABLE IF EXISTS STG_2097152;
CREATE TABLE dbo.STG_2097152 (ID BIGINT NOT NULL);
INSERT INTO dbo.STG_2097152 WITH (TABLOCK)
SELECT TOP (2097152) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN
FROM master..spt_values t1
CROSS JOIN master..spt_values t2;
Bu kesici uç bir saniyeden daha kısa sürede biter ve düşük sıkıştırmaya sahiptir:
DROP TABLE IF EXISTS dbo.CCI_BIGINT;
CREATE TABLE dbo.CCI_BIGINT (ID BIGINT NOT NULL, INDEX CCI CLUSTERED COLUMNSTORE);
INSERT INTO dbo.CCI_BIGINT WITH (TABLOCK)
SELECT ID % 16000
FROM dbo.STG_2097152
OPTION (MAXDOP 2);
Dengesiz dişlerin etkisini görebiliriz:
╔════════════╦════════════╦══════════════╦═══════════════╗
║ state_desc ║ total_rows ║ deleted_rows ║ size_in_bytes ║
╠════════════╬════════════╬══════════════╬═══════════════╣
║ OPEN ║ 13540 ║ 0 ║ 311296 ║
║ COMPRESSED ║ 1048576 ║ 0 ║ 2095872 ║
║ COMPRESSED ║ 1035036 ║ 0 ║ 2070784 ║
╚════════════╩════════════╩══════════════╩═══════════════╝
İplikleri dengeli olmaya ve aynı sıra dağılımına sahip olmaya zorlamak için yapabileceğimiz çeşitli püf noktaları var. İşte bunlardan biri:
DROP TABLE IF EXISTS dbo.CCI_BIGINT;
CREATE TABLE dbo.CCI_BIGINT (ID BIGINT NOT NULL, INDEX CCI CLUSTERED COLUMNSTORE);
INSERT INTO dbo.CCI_BIGINT WITH (TABLOCK)
SELECT FLOOR(0.5 * ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) % 15999
FROM dbo.STG_2097152
OPTION (MAXDOP 2)
Burada modül için tek bir sayı seçmek önemlidir. SQL Server, hazırlama tablosunu seri olarak tarar, satır numarasını hesaplar, ardından satırları paralel iş parçacıklarına yerleştirmek için yuvarlak robin dağıtımını kullanır. Bu da son derece dengeli ipliklerle sonuçlanacağımız anlamına geliyor.
Kesici uç, seri kesici uca benzer şekilde yaklaşık 40 saniye sürer. Güzel sıkıştırılmış satır grupları elde ederiz:
╔════════════╦════════════╦══════════════╦═══════════════╗
║ state_desc ║ total_rows ║ deleted_rows ║ size_in_bytes ║
╠════════════╬════════════╬══════════════╬═══════════════╣
║ COMPRESSED ║ 1048576 ║ 0 ║ 128568 ║
║ COMPRESSED ║ 1048576 ║ 0 ║ 128568 ║
╚════════════╩════════════╩══════════════╩═══════════════╝
Orijinal evreleme tablosundan veri ekleyerek aynı sonuçları elde edebiliriz:
DROP TABLE IF EXISTS dbo.CCI_BIGINT;
CREATE TABLE dbo.CCI_BIGINT (ID BIGINT NOT NULL, INDEX CCI CLUSTERED COLUMNSTORE);
INSERT INTO dbo.CCI_BIGINT WITH (TABLOCK)
SELECT t.ID % 16000 ID
FROM (
SELECT TOP (2) ID
FROM (SELECT 1 ID UNION ALL SELECT 2 ) r
) s
CROSS JOIN dbo.STG_1048576 t
OPTION (MAXDOP 2, NO_PERFORMANCE_SPOOL);
Burada türetilmiş tablo için yuvarlak robin dağılımı kullanılır, s
böylece her paralel iş parçacığında tablonun bir taraması yapılır:
Sonuç olarak, eşit olarak dağıtılmış tamsayılar eklerken, her bir benzersiz tamsayı 64 kereden fazla göründüğünde çok yüksek sıkıştırma görebilirsiniz. Bunun nedeni, farklı bir sıkıştırma algoritmasının kullanılması olabilir. Bu sıkıştırmayı elde etmek için CPU'da yüksek bir maliyet olabilir. Verilerdeki küçük değişiklikler, sıkıştırılmış satır grubu segmentinin boyutunda dramatik farklılıklara yol açabilir. En kötü durumu görmenin (CPU perspektifinden) en azından bu veri seti için vahşi olacağından şüpheleniyorum. Paralel uçlar yaparken görmek daha da zor.