SQL Server'ı sorgu koşullarını yazıldığı gibi çalıştırmaya zorlansın mı?


14

SQL Server 2008 R2 kullanıyorum ve bu sözde sorgu (SP) var:

select ...
from ...
WHERE    @LinkMode IS NULL
     AND (myColumn IN (...very long-running query...))
     ...
     ...

Sorun, ben SP yürütmek bile sorgu yürütmek için çok uzun zaman alır olmasıdır @LinkMode=2.

Fark ettiğiniz gibi, uzun süren sorgu yalnızca @LinkMode boşsa çalıştırılmalıdır (bu durum böyle değildir). Benim durumumda @LinkMode = 2!

Ancak, ben bunu değiştirmek eğer:

 select ...
    from ...
    WHERE    1=2
         AND (myColumn IN (...very long time exeted query...))
     ...
     ...

SP gelmez hızlı koş.

Daha önce duymuştum ki bazen optimizer kriterlerin sırasını optimize edebilir .

Yani soruyorum :

  • Optimize edici farklı bir rota seçse bile, kontrol edip etmekten daha hızlı ne olabilir =null? Yani, ben bu denetimi düşünüyorum if a==nullolduğunu çok daha hızlı diğer uzun sorguyu çalıştırarak daha ...

  • Nasıl olabilir zorlamak ben (aynı sırada) yazdım olarak sorgu çalıştırmak için SQL Server?

Yanıtlar:


22

Gail Shaw tarafından çok iyi açıklanmış olan " Catch-All Query " tuzağına düşüyorsunuz .

Sorunu özetlemek için: SQL Server, derleme sonrası bir sorgu planını önbelleğe alarak ve daha sonra önbelleği daha sonra derleme önce eşleşen bir sorgu planı için denetleyerek sorgu derleme önemli yükü optimize eder. Burada meydana gelen "eşleştirme" tamamen metindir, bu nedenle bir değişkenin gerçek değeri bunu etkilemez.

Bu % 99 oranında iyidir , ancak bazı durumlarda kötüdür . Kötü olduğu bir durum, birisinin WHERE yan tümcesi oluşturmaya çalıştığında, C, vb. Gibi kısa devre IF ifadesi gibi bir durum olduğu zaman, SQL derleyicisi ne olursa olsun çalışacak bir sorgu planı yapmak zorunda olduğu için bu iyi çalışmaz parametre değerlerinin gerçekte ne olduğunu ve WHERE yan tümcesinde bu "akıllı" mantıksal anahtarlama koşullarını işleyebilmesinin tek yolu, tüm tabloyu tarayan ve satırları giderken filtreleyen basit bir kaba kuvvet planı yapmaktır , herhangi bir dizin kullanmadan.

Şaşırtıcı olmayan bir şekilde, parametre / değişken değerleri ne olursa olsun, onları eşit bir şekilde yavaşlatır.


8

SQL sunucusunu, koşul koşullarınızı belirli bir sırayla yürütmeye zorlamanın garantisi yoktur. Optimize edici, bunları her zaman uygun gördüğü sırayla değerlendirecektir.

Yapabileceğiniz şey şudur:

IF @LinkMode IS NULL
BEGIN
    select ...
    from ...
    WHERE (myColumn IN (...very long time exeted query...))
         ...
         ...
END
ELSE
BEGIN
    select ...
    from ...
    WHERE ...
         ...
END

3

Bu bir seçenekse, sorgunun uygun biçimini yürütmek için bir IF deyimi kullanın. Ayrıca, SQL'de, db motoruna nasıl yapılacağını değil, nasıl yapılacağını söylersiniz - işler baştan sona yürütülmez. Tam olarak ne yapacağını tahmin etmek zor olabilir. Muhtemelen bunu biliyorsunuz;)


2

Dinamik SQL muhtemelen de işe yarayacaktır, çünkü bu durumda sorgu iyileştirici çalışma zamanında gerçek değerleri almalıdır (yanlışsam beni düzelt, aslında emin değilim ama benzer durumlar için kullanmayı hatırlıyor gibi görünüyor) . Ama bu konuda diğerleriyle birlikteyim, bir IF / ELSE deyimi size en iyi şekilde hizmet edecek çünkü tam olarak gerekli olanı yapacak en basit ve en kolay çözüm.

Henüz kullanmadıysanız ileride başvurmak için dinamik SQL için çalışan bir örneğe sahip korkunç çirkin bir site burada bulunabilir: örneğin: http://sqlusa.com/bestpractices/dynamicsql/


1

IF / ELSE yapısını öneririm. Sizin için uygun olmayan herhangi bir nedenle, her zaman WITH RECOMPILE seçeneğini kullanmayı düşünebilirsiniz.


Belki "if / else yapısının" neye benzeyebileceğini ayrıntılı bir şekilde anlatabilir misiniz? : D
jcolebrand

Her seferinde ideal bir plan oluşturacağından OPTION (RECOMPILE İLE) seçeneğini önerecektim - derleme gecikmesi yükü ekleyecekti, ancak bu durumda genel olarak daha iyi olduğundan şüpheleniyorum.
SqlRyan
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.