Remus, VARCHAR
sütunun maksimum uzunluğunun tahmini satır boyutunu etkilediğini ve bu nedenle SQL Server'ın sağladığı bellek izinlerini yararlı bir şekilde işaret etmiştir .
Cevabının "bundan kaskad olayı" kısmını genişletmek için biraz daha araştırma yapmaya çalıştım. Tam veya özlü bir açıklamam yok, ama bulduğum şey bu.
Betiği yeniden oluştur
Ben indeks oluşturma kabaca 10x sürümüm için sürece hangi üzerinde sahte veri kümesi üreten tam bir komut dosyası oluşturdumVARCHAR(256)
. Kullanılan veri aynıdır, ancak birinci tablo gerçek maksimum uzunlukta kullanır 18
, 75
, 9
, 15
, 123
, ve 5
, tüm sütun bir maksimum uzunluğa kullanırken 256
ikinci tabloda.
Orijinal tabloyu kodlama
Burada orijinal sorgunun yaklaşık 20 saniye içinde tamamlandığını ve mantıksal okumaların tablo boyutuna eşit olduğunu görüyoruz ~1.5GB
(195K sayfa, sayfa başına 8K).
-- CPU time = 37674 ms, elapsed time = 19206 ms.
-- Table 'testVarchar'. Scan count 9, logical reads 194490, physical reads 0
CREATE CLUSTERED INDEX IX_testVarchar
ON dbo.testVarchar (s1, s2, s3, s4)
WITH (MAXDOP = 8) -- Same as my global MAXDOP, but just being explicit
GO
VARCHAR (256) tablosunu anahtarlama
İçin VARCHAR(256)
masa, biz geçen zaman önemli ölçüde arttığını görüyoruz.
İlginçtir, ne CPU zamanı ne de mantıksal okumalar artmaz. Tablonun tamamen aynı verilere sahip olduğu göz önüne alındığında bu mantıklıdır, ancak geçen sürenin neden bu kadar yavaş olduğunu açıklamaz.
-- CPU time = 33212 ms, elapsed time = 263134 ms.
-- Table 'testVarchar256'. Scan count 9, logical reads 194491
CREATE CLUSTERED INDEX IX_testVarchar256
ON dbo.testVarchar256 (s1, s2, s3, s4)
WITH (MAXDOP = 8) -- Same as my global MAXDOP, but just being explicit
GO
G / Ç ve bekleme istatistikleri: orijinal
Biraz daha fazla ayrıntı yakalarsak ( yazdığım bir prosedür olan p_perfMon kullanarak ), G / Ç'nin büyük çoğunluğunun LOG
dosyada yapıldığını görebiliriz . Gerçekte ROWS
(ana veri dosyası) nispeten az miktarda I / O görüyoruz ve birincil bekleme türü, LATCH_EX
bellek içi sayfa çekişmesini gösteriyor.
Paul Randal'a göre , eğirme diskimin "kötü" ve "şok edici derecede kötü" arasında bir yerde olduğunu da görebiliriz :)
G / Ç ve bekleme istatistikleri: VARCHAR (256)
İçin VARCHAR(256)
sürümü, I / O ve beklemek istatistikleri tamamen farklı görünüyor! Burada veri dosyasında ( ROWS
) G / Ç'de büyük bir artış görüyoruz ve durma süreleri artık Paul Randal'ın "WOW!"
# 1 bekleme türünün şimdi olması şaşırtıcı değil IO_COMPLETION
. Peki neden bu kadar çok G / Ç üretiliyor?
Gerçek sorgu planı: VARCHAR (256)
Sorgu planından, Sort
operatörün VARCHAR(256)
sorgu sürümünde yinelemeli bir dökülmeye (5 seviye derinlik!) Sahip olduğunu görebiliriz . (Orijinal sürümde hiçbir dökülme yoktur.)
Canlı sorgu ilerlemesi: VARCHAR (256)
Biz yapabilirsiniz SQL 2014+ canlı sorgu ilerlemesini görüntülemek için sys.dm_exec_query_profiles kullanın . Orijinal versiyonda, tüm Table Scan
ve Sort
herhangi bir dökülme olmadan işlenir ( boyunca spill_page_count
kalır 0
).
In VARCHAR(256)
sürümü Ancak biz o sayfa sızıntıları hızla için birikir görebilirsiniz Sort
operatörü. İşte sorgu tamamlanmadan hemen önce sorgu ilerlemesinin bir anlık görüntüsü. Buradaki veriler tüm iş parçacıkları arasında toplanır.
Her bir iş parçacığını ayrı ayrı kazarsam, 2 iş parçacığının sıralamayı yaklaşık 5 saniye içinde tamamladığını görüyorum (genel olarak 20 saniye, tablo taramasında 15 saniye geçirdikten sonra). Tüm iş parçacıkları bu hızda ilerlerse, VARCHAR(256)
dizin oluşturma işlemi orijinal tabloyla hemen hemen aynı zamanda tamamlanırdı.
Ancak, geri kalan 6 iş parçacığı çok daha yavaş bir oranda ilerler. Bunun nedeni, belleğin tahsis edilme şekli ve iş parçacıklarının veri döktükleri için G / Ç tarafından tutulma biçimleri olabilir. Ama emin değilim.
Ne yapabilirsin?
Denemeyi düşünebileceğiniz birkaç şey vardır:
- Önceki bir sürüme geri dönmek için satıcıyla birlikte çalışın. Bu mümkün değilse, satıcının bu değişiklikten memnun olmadığınızı, böylece gelecekteki bir sürümde geri almayı düşünebilmesini sağlayın.
- Dizininizi eklerken, geçerli sunucu düzeyi ayarınızdan daha düşük bir sayı olan
OPTION (MAXDOP X)
yeri kullanmayı düşünün X
. Makinemdeki OPTION (MAXDOP 2)
bu özel veri setini kullandığımda , VARCHAR(256)
sürüm tamamlandı 25 seconds
(8 iş parçacıklı 3-4 dakika ile karşılaştırıldığında!). Dökülme davranışının daha yüksek paralellik ile şiddetlenmesi mümkündür.
- Ek donanım yatırımı mümkünse, sisteminizdeki G / Ç'yi (olası darboğaz) profil haline getirin ve dökülmelerden kaynaklanan G / Ç'nin gecikmesini azaltmak için bir SSD kullanmayı düşünün.
daha fazla okuma
Paul White, SQL Server türlerinin iç kısımlarında ilgi çekici olabilecek güzel bir blog yayınına sahiptir . Paralel çeşitler için dökülme, iplik eğriliği ve bellek tahsisi hakkında biraz konuşur.