Sütun boyutu arttıktan sonra dizin oluşturmak neden daha uzun sürüyor?


18

Tedarikçimiz, tüm veritabanındaki hemen hemen her sütunda sütun genişliklerini değiştirdi. Veritabanı yaklaşık 7 TB, 9000+ tablodur. 5.5 milyar satır içeren bir tabloda dizin oluşturmaya çalışıyoruz. Satıcının yeni sürüme geçirilmesinden önce dizini 2 saat içinde oluşturabiliriz. Şimdi günler sürüyor. Yaptıkları herhangi bir varchar (xx) boyutunu varchar'a (256) yükseltmektir. Yani çoğu sütun varchar (18) veya varchar (75) vb.

Her neyse, birincil anahtar genişliği 126 karakter olan 6 sütundan oluşur. Yükseltmeden sonra, birincil anahtar 1283 karakterdir ve SQL Server sınırını 900 karakter ihlal eder. Tüm tablo sütunu genişliği toplam 1049 kombine varchar sayısından 4009 toplam kombine varchar sayısına geçti.

Verilerde bir artış yoktur, tablo tüm sütun genişliği artışından önce olduğundan daha fazla "yer" almaz, ancak bir dizin kadar basit bir şey oluşturma performansı artık mantıksız bir zaman almaktadır.

Herkes yapılan tek şey sütunların boyutunu artırmak iken oluşturmak ve dizine eklemek neden bu kadar uzun sürüyor açıklayabilir misiniz?

Oluşturmaya çalıştığımız dizin pk kümelenmiş dizin olduğundan kümelenmemiş. Dizini oluşturmak için yapılan birkaç denemeden sonra vazgeçtik. Bence tamamlanmadan 4 ya da 5 gün koştu.

Ben bir dosya sistemi anlık görüntü alarak üretim dışı bir ortamda denedim ve daha sessiz bir sunucuda veritabanı getirdi.

Yanıtlar:


12

Remus, VARCHARsü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 256ikinci 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 LOGdosyada 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_EXbellek 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 :)

resim açıklamasını buraya girin


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?

resim açıklamasını buraya girin


Gerçek sorgu planı: VARCHAR (256)

Sorgu planından, Sortoperatö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.)

resim açıklamasını buraya girin


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 Scanve Sortherhangi bir dökülme olmadan işlenir ( boyunca spill_page_countkalır 0).

In VARCHAR(256)sürümü Ancak biz o sayfa sızıntıları hızla için birikir görebilirsiniz Sortoperatö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.

resim açıklamasını buraya girin

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.

resim açıklamasını buraya girin


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.


11

Ara sıralama tablosu iki durum arasında farklı şekilde tahmin edilecektir. Bu VARCHAR(256), 'ideal' taleple karşılaştırıldığında farklı bellek hibesi taleplerine ( daha büyük olacaktır) ve muhtemelen çok daha küçük bir gerçek hibeye (yüzde olarak) yol açacaktır . Sanırım bu sıralama sırasında dökülmelere neden oluyor.

Senaryo Geoff den test (sadece 100 bin satır) Sıralanan tahmini satır boyutu (141B vs 789B) açıkça görebiliyorum. Bundan olayların çağlayanı.


8
Eminim Paul, belki de dev ekibi tarafından öğrenme materyali olarak kullanılacak çağrı yığınları da dahil olmak üzere daha kapsamlı ve eksiksiz bir cevap kanıtlayacaktır. Yine ...
Remus Rusanu
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.