LATCH_EX Kaynak Bekler METADATA_SEQUENCE_GENERATOR


11

Envanter raporu üreten bir sürecimiz var. İstemci tarafında, işlem yapılandırılabilir sayıda işçi iş parçacığını bölerek rapor için çok sayıda mağazadan (potansiyel olarak binlerce, genellikle düzinelerce) bir mağazaya karşılık gelen bir veri yığını oluşturur. Her işçi iş parçacığı, saklı yordamı yürüten bir web hizmetini çağırır.

Her parçayı işlemek için kullanılan veritabanı işlemi, #Temporary tablosuna bir grup veri toplar. Her bir işlem yığınının sonunda, veriler tempdb'de kalıcı bir tabloya yazılır. Son olarak, işlemin sonunda, istemci tarafındaki bir iş parçacığı kalıcı tempdb tablosundan tüm verileri ister.

Bu raporu ne kadar çok kullanıcı çalıştırırsa o kadar yavaşlar. Veritabanındaki etkinliği analiz ettim. Bir noktada, sürecin bir noktasında engellenen 35 ayrı istek gördüm. Tüm bu SPID'ler LATCH_EXkaynak üzerinde 50 ms'lik bekleme süresine sahipti METADATA_SEQUENCE_GENERATOR (00000010E13CA1A8). Bir SPID'nin bu kaynağı var ve diğerleri de engelliyor. Bir web aramasında bu bekleme kaynağı hakkında hiçbir şey bulamadım.

Kullandığımız tempdb tablosunda bir IDENTITY(1,1)sütun var. Bu SPID'ler KİMLİK sütununu bekliyor mu? Engellemeyi azaltmak veya ortadan kaldırmak için hangi yöntemleri kullanabiliriz?

Sunucu bir kümenin parçasıdır. Sunucu, 64 bit Windows 2008 R2 Enterprise'da 64 bit SQL Server 2012 Standard Edition SP1 çalıştırıyor. Sunucuda 64 GB RAM ve 48 işlemci vardır, ancak standart sürüm olduğu için veritabanı yalnızca 16'yı kullanabilir.

(Tüm bu verileri tutmak için tempdb'de kalıcı bir tablo kullanma tasarımı beni heyecanlandırmaz. Bunu değiştirmek ilginç bir teknik ve politik zorluk olacaktır, ancak önerilere açığım.)

GÜNCELLEME 4/23/2013

Microsoft ile bir destek vakası açtık. Daha fazla bilgi edindikçe bu soruyu güncel tutacağım.

GÜNCELLEME 5/10/2013

SQL Server destek mühendisi, beklemelerin KİMLİK sütunundan kaynaklandığını kabul etti. KİMLİK'in kaldırılması beklemeleri ortadan kaldırdı. SQL 2008 R2'de sorunu çoğaltamadık; yalnızca SQL 2012'de gerçekleşti.


İşlem temel olarak # Geçici tablolardan kalıcı tabloya veri kopyalıyor mu yoksa bu adımda ek dönüştürme mantığı var mı?
Jon Seigel

Beklediği adımda, tek bir mağazanın stok kayıtlarını dönüşüm olmaksızın kalıcı tabloya kopyalıyor. Kalıcı tablonun içinde sürekli çalışabiliriz, ancak programcı, verilerdeki sık güncellemelerin PAGE kilitlerine dönüştürülmesini önlemek için tutma alanı olarak #Temporary tablosu kullanmayı tercih etti.
Paul Williams

Yanıtlar:


4

Sorunu kimlik değerlerinin oluşturulmasına ayırabileceğinizi varsayarsak (bu sütunu test olarak kaldırmayı deneyin), ne tavsiye ederim:

  1. IDENTITYÖzelliği son tablodaki sütundan kaldırın .
  2. #Temporary tablolarının her birinde kimlik değerleri oluşturun.
  3. Son tabloyu yüklerken, belirli bir mağaza için sayısal bir tanımlayıcıyı 2. adımdaki kimlik değerleriyle birleştirin.

3 ve 4 numaralı mağaza kimlikleriniz varsa, bunun gibi nihai kimlik değerlerine sahip olursunuz:

3000000001
3000000002
3000000003
...
4000000001
4000000002
...

Ya da buna benzer bir şey. Kaptın bu işi.

Bu IDENTITY, nihai sonuçtaki benzersizliği korurken jenerasyonda serileştirme ihtiyacını ortadan kaldıracaktır .

Alternatif olarak, işlemin nasıl çalıştığına bağlı olarak, hesaplanan son kimlik değerlerini # Geçici tablolara ekleyin. Daha sonra UNION ALL, verileri bir araya getirme gereğini ortadan kaldırarak, bunları bir araya getiren bir görünüm oluşturabilirsiniz .


Cevap için teşekkürler. Sorunun bu olup olmadığını kabul ediyorum, üretilen bazı anahtarları (veya hiç anahtarı kullanma) sorunu çözebilir. Bu sorunla ilgili olarak Microsoft ile bir dava açtık. Sonucu buraya gönderirim ve sorunun bu olduğunu kabul ederlerse cevabınızı kabul edeceğim.
Paul Williams

@ Paul: Lütfen bana bildirin; Ben de meraklıyım. Sizin gibi, web üzerinde bu mandalla ilgili hiçbir şey bulamadım, ancak kimlik / sekans serileştirmesi kesinlikle makul. Bu darboğazın olup olmadığını söylemek zor olsa da, değerler için rekabet eden 30'dan fazla iş parçacığıyla, muhtemelen görünüyor. Ayrıca, yardımcı olup olmadığını görmek için her bir #Temporary tablosundan seri olarak (paralel yerine) kopyalamayı deneyebilirsiniz.
Jon Seigel

2
SQL Server mühendisi muhtemelen IDENTITYsütun olduğunu kabul etti . Zaten geniş kümelenmiş dizinden çıkardık ve sütunu tamamen kaldırdık. Gerekli değildi. Daha sonra bu LATCH_EX beklemeleri ortadan kalktı. SQL 2008 R2'deki beklemeleri çoğaltamadık. Sorun yalnızca SQL Server 2012'de oldu.
Paul Williams

@ Paul: Takip ettiğiniz için teşekkürler. Çok ilginç. IDENTITYDeğerler üreten kod 2012 yılında yeni yeni dizi oluşturma şeyler kullanmak için yeniden yazıldığını tahmin ediyorum . <2012, farklı bir mandal türü görebilirsiniz, ancak mükemmel bir sorun varsa, o zaman orada görünüyor kodda bir gerileme. Her durumda, IDENTITYsütunu kaldırmak en güvenli şeydir.
Jon Seigel

Kimlik yerine bir 'SEQUENCE' (SQL 2012'de yeni) kullanmaya çalışabilirsiniz
Bogdan Maxim

7

(Şubat 2019'da güncellendi)

Bu eski bir yazı, sonunda Microsoft'u bunun gerçekleşmesinin gerçekten bir kusur olduğu konusunda ikna etmeyi başardığımı söyledi.

Güncelleme: MS Hatayı onayladı ve 12628722 numaralı hata verdi.

Bu gönderiyi geçen Kasım 2018'de, Sql Server 2005'ten Sql Server 2017'ye yükselttikten sonra çok fazla acı çekmeye başladığımızda gördüm. Aniden 10 saniye süren 3,3 milyon satırlık tablo, aniden 10 saniye almaya başladı. Identitysütun içeren tablolarda dakika .

Bunun arkasında iki sorun olduğu ortaya çıktı:

  1. Microsoft, Sql Server 2014'teki davranışı, Toplu Ek'lerin paralel çalışmasına zorlamak için değiştirdi - önceki sürümlerde Toplu Eklere Serileştirilmiş bir plan verildi.
  2. 32 çekirdekli kutumuza paralel olarak koştuktan sonra, motor çekirdeklerin işi kilitlemekten çok kilitlemesiyle daha fazla zaman harcadı.

4 hafta sürdü ama tatilden hemen sonra Noel Babadan gecikmiş bir hediye aldım - sorunun gerçekten bir kusur olduğunu onaylama.

Bu sorun çözülene kadar bulduğumuz birkaç olası çözüm vardır:

  1. Option (MaxDop 1)Toplu eki tekrar serileştirilmiş bir plana dönüştürmek için sorguda kullanın .
  2. Kimlik sütununu yayınlayarak maskeleyin (ör. Select Cast(MyIdentityColumn As Integer) As MyIdentityColumn)
    • bu, kimlik özelliğinin kullanırken kopyalanmasını önler SELECT...INTO
  3. Yukarıda açıklandığı gibi kimlik sütununu kaldırın.
  4. Serileştirilmiş bir planı yeniden oluşturmak için veritabanı uyumluluk modunu Sql Server 2012 veya daha düşük olarak değiştirin.

Güncelleme: MS'in uygulayacağı düzeltme, bu tür Ekleri bir Serialized plan kullanarak geri döndürmek olacaktır . Bu, Sql Server 2017 CU14 için planlanmıştır ( Sql Server'ın diğer sürümlerinde haber yok - özür dileriz!). Uygulandığında , İzleme Bayrağı 9492'nin sunucu düzeyinde veya üzerinden açılması gerekirDBCC TraceOn .

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.