Herkesin bir Full Metal Pocket Protector’a sahip olmadığının ve hepimizin günlerimizi sunucularımızdan her CPU döngüsünü ve I/O işlemini çıkarmak için sorgu ve dizin ayarlamanın derinliklerine dalmakla geçiremeyeceğimizin farkındayız.
Peki bunun bizimle ne ilgisi var?
Bizimle ilgisi var, çünkü WHERE cümlenizi hala kötü biçilendirebiliyoruz. Hala sütunların etrafına ifadeler koyuyor ve bu çıktıyı bir değerle veya başka bir ifadeyle karşılaştırıyoruz.
First_Name + ‘ ‘ + Last_Name = ‘Fahrettin Cüreklibatur’ gibi bir şey yaptığınız veya daha da kötüsü, bir tarihi tamamen YEAR(), MONTH() ve DAY() olarak ayırdığımız ve hepsini değerlerle karşılaştırdığımız zamanları düşünün.
Daha Yaygın
Bazen insanlar DATEADD’nin var olduğunu unuturlar. Doğrudan DATEDIFF’e gidiyorlar, çünkü kulağa daha mantıklı geliyor.
Ancak bu, özellikle çok fazla veriyle uğraşıyorsanız ya da WHERE cümlesi daha karmaşık bir JOIN serisinin parçasıysa başınızı büyük belaya sokabilir. Sadece herhangi bir dizini verimli bir şekilde kullanmamakla kalmaz, aynı zamanda diğer işlemler için kardinalite tahminini gerçekten mahvedebilir. Bu tehlike neye benziyor?
1
2 3 |
SELECT COUNT(*)
FROM dbo.SalesOrders AS so WHERE DATEDIFF(DAY, CONVERT(DATE, so.OrderDate), GETUTCDATE()) = 55 |
Her şey yolunda gözüküyor
Yine de bununla ilgili bazı sorunlar var.
Burada cardinality estimator konusunda fena iş çıkarmadık. Sihirli Matematik 10.000 satırlık tablomuz için yaklaşık olarak doğru tahminde bulundu. Ancak Gelişmiş Sorgu Planı Teknolojisindeki gelişmeler (ipucu: SQL SERVER 2008R2’DEN ÇIKIN), gerçekte ihtiyacımız olan 5003 satırı almak yerine, dizindeki bu satırların 10.000’ini okuduğumuzu görmemizi sağlıyor. Nasıl daha iyisini yapabiliriz?
İşleri biraz tersine çevireceğiz! Fonksiyonu sütundan alıp yüklemimizin üzerine koyacağız. Bunun neden iyi olduğunu bilirsiniz. Optimizer ifadeyi sorguya katlamasına ve dizin erişimine doğru itmesine olanak tanır.
1
2 3 |
SELECT COUNT(*)
FROM dbo.SalesOrders AS so WHERE CONVERT(DATE, so.OrderDate) = DATEADD(DAY, -55, CONVERT(DATE, GETUTCDATE())) |
Şimdi daha ucuz bir dizin araması elde ediyoruz, fazladan 4997 satır okumuyoruz ve cardinality estimator doğru. Yine, orijinalinde çok kötü değildi, ancak burada kolay kurtulduk.
Aşağıdaki planlara göz atabiliriz;
Her iki plana da OrderDate sütunundaki dizinimiz yardımcı oluyor.Tam satır sayılarını bulmak için bu tabloyu şişirmedik, ancak başka bir yerde çalıştığını gördük. İkinci sorgu da tarama yapsa bile daha ucuz olacaktır.