Sorgu SQL 2005 ve SQL 2008R2'de Farklı Çalışıyor


9

Ofisimde oldukça çirkin, ancak üretimde ve geliştirme ortamında oldukça iyi çalışan bir sorgu var (sırasıyla 20sn ve 4sec). Ancak test ortamımızda 4 saatten fazla sürer. SQL2005 (+ en son yamalar) üretim ve geliştirmede çalışıyor. Test sırasında SQL2008R2 çalışıyor.

Sorgu Planına bir göz attım ve SQL2008R2'nin döndürülen satırları bağlantılı sunucudan depolamak için bir Tablo Biriktirme (tembel biriktirme) aracılığıyla TempDB kullandığını gösteriyor. Bir sonraki adım, sorgunun% 96,3'ünü tüketen Yuvalanmış Döngüler'i (sol anti yarı birleşim) gösteriyor. İki operatör arasındaki hat 5.398 MB'tır!

SQL 2005 için sorgu planı tempdb ve sol anti yarı birleştirme kullanımını gösterir.

Sterilize edilmiş kod ve yürütme planları 2005 planını en üstte, 2008R2 en altta planlıyor.

Sert yavaşlama ve değişime neden olan nedir? Farklı bir infaz planı görmeyi bekliyordum, bu beni rahatsız etmiyor. Sorgu süresindeki dramatik yavaşlama beni rahatsız eden şey.

Altta yatan donanıma bakmalı mıyım, 2008R2 sürümü tempdb kullandığından bunun kullanımını nasıl optimize edebileceğime bir göz atmam gerekiyor mu?

Sorguyu yazmanın daha iyi bir yolu var mı?

Yardım için teşekkürler.

    INSERT INTO Table1_GroupLock (iGroupID, dLockedDate)
SELECT 
 Table1.iGroupID,
 GETDATE()
FROM Table1
WHERE 
 NOT EXISTS (
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE 
   (
    Alias2.FirstName + Alias2.LastName = dbo.fnRemoveNonLetter(Table1.FullName)
    AND NOT dbo.fnRemoveNonLetter(Table1.FullName) IS NULL
    AND NOT Alias2.FirstName IS NULL 
    AND NOT Alias2.LastName  IS NULL
   ) OR (
    Alias2.FamilyName = dbo.fnRemoveNonLetter(Table1.FamilyName)
    AND Alias2.Child1Name = dbo.fnRemoveNonLetter(Table1.Child1Name)
    AND NOT dbo.fnRemoveNonLetter(Table1.FamilyName) IS NULL
    AND NOT dbo.fnRemoveNonLetter(Table1.Child1Name) IS NULL
    AND NOT Alias2.Familyname IS NULL
    AND NOT Alias2.Child1Name IS NULL
   ) OR (
    Alias2.StepFamilyName = dbo.fnRemoveNonLetter(Table1.StepFamilyName)
    AND Alias2.StepFamilyNameChild1 = dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2)
    AND NOT Alias2.StepFamilyName IS NULL
    AND NOT Alias2.StepFamilyNameChild1 IS NULL
    AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyName) IS NULL
    AND NOT dbo.fnRemoveNonLetter(Table1.StepFamilyNameChild2) IS NULL
   )  
 ) AND NOT EXISTS (
  SELECT 1
  FROM Table3
  INNER JOIN Table4
   ON Table4.FirstNameType = Table3.FirstNameType 
  INNER JOIN table5
   ON table5.LastNameType = Table3.LastNameType 
  WHERE 
   Table3.iGroupID = Table1.iGroupID
   AND Table3.bIsClosed = 0
   AND Table4.sNameTypeConstant = 'new_lastname'
   AND table5.sFirstNameConstant = 'new_firstname'
 )

SQL-2005


SQL2008R2

:: EDIT :: Sorguyu, farklı bir SQL2005 örneğinden, hemen hemen "iyi olanla" aynı yürütme planıyla yürüttüm. İki 2005 sürümünün 2008R2 bağlantılı sunucuda nasıl çalıştığından emin değilsiniz, 2008R2 örneklerinin 2008R2 örneklerinden daha iyi.

Kodun bazı işleri kullanabileceğini inkar etmese de, sorun olan kod olsaydı, tüm denemelerimde aynı 'exec exec planlarını göremez miydim? SQL sürümünden bağımsız olarak?

:: EDIT :: Her iki 2008R2 örneğine de SP1 ve CU3 uyguladım, hala zar yok. Özellikle bağlı sunucuda kollokasyon ayarladım, zar yok. Özellikle kullanıcı acct izinlerini her iki örnekte sysadmin olacak şekilde ayarladım, zar yok. Ayrıca sql server 2008 dahili ve sorun giderme hatırladım, biz bunu nasıl izleyebilir miyim göreceğiz.

Yardım ve ipuçları için herkese teşekkürler.

:: EDIT :: Bağlantılı sunucuda çeşitli izin değişiklikleri yaptım. Ben SQL girişleri, etki alanı girişleri kullandım, ben kimliğine bürünmüş kullanıcılar, "Bu güvenlik bağlamı kullanılarak yapılabilir" seçeneğini kullandım. Bağlı sunucunun her iki tarafında sunucuda sysadmin hakları olan kullanıcılar oluşturdum. Fikirlerim tükendi.

Hala neden SQL2005 sorguyu SQL2008R2 çok dramatik bir şekilde farklı yürütüyor bilmek istiyorum. Kötü bir sorgu olsaydı, SQL2005 ve SQL2008R2 üzerinde 4 + saat çalışma süresi görecektim.

Yanıtlar:


5

Sorguyu elden geçirmeni istiyorum.

Sersemlik sorunlarınız var ve hatta orada da sorguyu incitecek skaler fonksiyon çağrıları kullanıyorsunuz. Tablo2'de bir FullName hesaplanmış sütun yapmak ve bir dizin koymak isteyebilirsiniz, endeks INCLUDEs FirstName ve LastName emin olun. Ayrıca diğerine yardımcı olan dizinler eklemelisiniz

Ayrıca, "RemoveNonLetter" işlevselliğinizi yapmak için satır içi tablo değerli bir işlev yapın ve muhtemelen burada yaptığım gibi UYGULA'yı kullanarak sorgunuzu yeniden kullanmak için yeniden çalışın.

Ve Paul'un cevabının bahsettiği hatayı kesinlikle kontrol edin .

INSERT INTO Table1_GroupLock (iGroupID, dLockedDate)
SELECT 
 Table1.iGroupID,
 GETDATE()
FROM Table1
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.FullName)) AS fn (FullName)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.FamilyName)) AS famn (FamilyName)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.Child1Name)) AS c1n (Child1Name)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.StepFamilyName)) AS sfn (StepFamilyName)
OUTER APPLY (SELECT NonLettersRemoved FROM dbo.ifnRemoveNonLetter(Table1.StepFamilyNameChild2)) AS sfnc2 (StepFamilyNameChild2)
WHERE 
 NOT EXISTS (
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE Alias2.FullName = fn.FullName
  UNION ALL
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE Alias2.FamilyName = famn.FamilyName AND Alias2.Child1Name = c1n.Child1Name
  UNION ALL
  SELECT 1
  FROM LinkedServer.Database.Table2 Alias2
  WHERE Alias2.StepFamilyName = sfn.StepFamilyName AND Alias2.StepFamilyNameChild1 = sfnc2.StepFamilyNameChild2
 ) 
 AND NOT EXISTS (
  SELECT 1
  FROM Table3
  INNER JOIN Table4
   ON Table4.FirstNameType = Table3.FirstNameType 
  INNER JOIN table5
   ON table5.LastNameType = Table3.LastNameType 
  WHERE 
   Table3.iGroupID = Table1.iGroupID
   AND Table3.bIsClosed = 0
   AND Table4.sNameTypeConstant = 'new_lastname'
   AND table5.sFirstNameConstant = 'new_firstname'
 )
;

6

Önceki cevaplara ek olarak, plan gerilemesinin nedeni, plan bir Anti Yarı Katılma içerdiğinde bilinen bir kardinalite tahmin hatasından kaynaklanıyor olabilir . Bkz. KB 2222998

2005 planının kabul edilebilir performans ürettiği varsayılarak, sunucuyu bu düzeltmeyi içeren bir sürüme getirmeyi (ve TF4199'un etkinleştirmesini sağlama) sizi 'iyi' plana döndüreceğini görebilirsiniz.

Bununla birlikte, bu sorguyu iyileştirmek için başka birçok fırsat var, bu yüzden bunun yerine buna konsantre olmak için iyi bir zaman olabilir.


5

Uzak verilerin yerel olarak biriktirilmesini öneriyorum çünkü

  1. Bağlı Sunucu ayarları (harmanlama gibi) aynı değil
  2. Bağlı sunucu ayarlarına rağmen yerel harmanlama uzaktan kumanda ile aynı değil
  3. Sorgu, izinler nedeniyle uzaktan doğru şekilde çalıştırılamıyor

Nokta 1 için bkz. Sp_serveroption
Ve nokta 2 için, aynı zamanda sunucu / db harmanlamalarını da kontrol edin.

3. nokta için Linchi Shea'dan bunlara bakınız:

SQL Server'dan tüm verileri yerel olarak işlemesini istersiniz, buradaki yanıma göre: Bir görünümde OPENQUERY kullanmanın performans sonuçları

Düzenle

İkinci bakışta, bir yerine "iyi" planında 2 uzaktan çağrı görüyorum. Bu, burada söylediğimi doğruluyor


Uzun gecikme için özür dilerim. 1: Bağlı sunucu ayarlarını kontrol ettim, bunlar aynı 2: Ayrıca kontrol ettim ve bağlı sunucu özelliklerinin uzak sunucuya harmanlanmasını dolaylı olarak ayarladım. 3: Hala A / B testi yapmak için çalıştığım güvenlik bağlamı. Hala çok farklı yürütme planlarının arkasındaki mantık üzerinde duruyorum. R2 sunucusundan R2 sunucusuna sadece seçimi çalıştırır (150K satırların çok üzerinde çeker), sonra birleşimleri yapar. 2005'ten R2'ye kadar, uzak sunucuda seçimleri yapar ve birleşir. Her iki senaryo için de güvenlik bağlamı aynıdır.
RateControl

3

Verigodundan sorgu yorumunuzu yeniden yazmayı deneyin +1.

Ayrıca bağlantılı sunucu tarafında bu yavaşlamaya yol açan bir izin sorunu içine darbeleme olup olmadığını merak ediyorum. Bir süre önce bu bağlantılı sunucu yavaşlaması hakkında blog yazdım . İzinleri doğrulamaya değer olabilir (SQL bağlantılı bir sunucu mu? Yoksa başka bir DBMS mi?

Bu sorguyu denemek ve ortamı dışlamak için hala test ortamında SQL Server 2005 var mı?

Yükseltmeden bu yana istatistikleri yeniden oluşturdunuz mu?


3

Bu karşılaştırmada çok fazla sorun var ... Nereden başlayacağımı bilmiyorum.

  1. Üretim ve test makineleriniz için tam özellikleri edinin.

  2. Her iki ortamda da çeşitli bağlı sunucular arasındaki ağ bağlantılarını belirleyin. Aynı hızda mı? Her iki ortamda da sunucular birbirinin yanında mı?

  3. Bağlı sunucuları KULLANMAMAK için sorguyu yeniden yazabilmenin herhangi bir yolu var mı? Sunucular arasında tablolara katılmak sizi topoloji değişikliklerine karşı savunmasız bırakır ve çoğu durumda korkunç bir şekilde yavaşlar.

  4. NOT ve OR'lerin kullanımı genellikle tam tablo taramalarına yol açar. Sorguyu yeniden yazmayı deneyin.

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.