SQL Server değerlendirmek için izin mi A <> B
olduğu A < B OR A > B
ifadelerden birinin belirli olmayan olsa bile,?
Bu biraz tartışmalı bir konu ve cevap nitelikli bir "evet".
Farkında olduğum en iyi tartışma, Itzik Ben-Gan'ın Connect hata raporunda , NEWID ve Tablo İfadeleri ile Hata mesajı düzeltmeyecek şekilde yanıtlandı . Connect o zamandan beri emekli oldu, bu yüzden oradaki bağlantı bir web arşivi. Maalesef, Connect'in ölümüyle birçok faydalı materyal kaybedildi (ya da bulması zorlaştı). Her neyse, Microsoft'tan Jim Hogg'dan en yararlı alıntılar:
Bu konunun tam ortasına isabet ediyor - bir programın anlamını değiştirmek için optimizasyona izin veriliyor mu? Yani: eğer bir program belirli cevaplar verir, fakat yavaş çalışırsa, bir Sorgu Optimize Edici'nin bu programı daha hızlı çalıştırmasını sağlamak meşru mudur, ancak verilen sonuçları da değiştirebilir mi?
"HAYIR!" Diye bağırmadan önce (benim kendi kişisel eğilimim de :-) düşünün: iyi haber, vakaların% 99'unda cevapların aynı olduğu. Yani Sorgu Optimizasyonu açık bir kazançtır. Kötü haberse, eğer sorgu yan etki kodunu içeriyorsa, o zaman farklı planlar CAN gerçekten farklı sonuçlar verir. Ve NEWID (), farkı ortaya çıkaran böyle bir yan etkileyici (deterministik olmayan) 'işlevdir'. [Eğer deney yaparsanız, başkalarını tasarlayabilirsiniz - örneğin, AND cümlelerinin kısa devre değerlendirmesi: ikinci cümleyi bir aritmetik sıfıra bölme - atma - birinci cümleden ÖNCE ikinci maddeyi uygulayabilir] Bu, yansıtır. Craig'in bu konudaki herhangi bir yerindeki açıklaması, SqlServer'ın skaler operatörleri çalıştırıldığında garanti etmediğini açıklıyor.
Öyleyse, bir seçeneğimiz var: deterministik olmayan (yan-etkileyici) kodun varlığında belirli bir davranışı garanti etmek istiyorsak - ki JOIN'lerin sonuçları, örneğin, iç içe geçmiş bir uygulamanın anlamını takip eder - o zaman biz UC'nin işaret ettiği gibi, bu davranışı zorlamak için uygun SEÇENEKLERİ kullanabilir. Ancak sonuçta ortaya çıkan kod yavaş çalışacaktır - bu, aslında, Sorgu Optimize Edici'yi azaltmanın maliyetidir.
Tüm bunlar, Sorgu Optimize Edici’yi NEWID () için "beklendiği gibi" davranışı yönünde hareket ettiriyoruz - "beklendiği gibi sonuçlar" için performans düşüyor.
Zaman içinde bu konuda davranış değişikliğinin bir örneği NULLIF, RAND () gibi deterministik olmayan fonksiyonlarla yanlış çalışır . COALESCE
Beklenmeyen sonuçlar üretebilen ve aynı zamanda yavaş yavaş ele alınan bir alt sorguyla birlikte kullanılan başka benzer durumlar da vardır .
Jim devam ediyor:
Döngüyü kapatıyorum. . . Bu soruyu Dev ekibi ile tartıştım. Ve nihayetinde, aşağıdaki sebeplerden dolayı mevcut davranışı değiştirmemeye karar verdik:
1) Optimize edici, skalar fonksiyonların zamanlamasını veya uygulama sayısını garanti etmez. Bu uzun vadeli bir inanç olduğunu. Bu, temel optimizasyonun optimize ediciye sorgu planı yürütmede önemli iyileştirmeler sağlaması için yeterli özgürlüğü sağlar.
2) Bu "satır başına bir davranış" yeni bir sorun değil, ancak geniş bir şekilde tartışılmamış. Yukon sürümünde davranışını değiştirmeye başladık. Ancak, her durumda, tam olarak ne anlama geldiğini tam olarak tespit etmek oldukça zordur! Örneğin, nihai sonuç için 'yolda' hesaplanan geçici satırlar için geçerli midir? - bu durumda açıkça seçilen plana bağlıdır. Yoksa yalnızca sonuçta tamamlanan sonuçta görünecek olan satırlar için de geçerli midir? - Burada katılıyorum, çünkü katılıyorum!
3) Daha önce de belirttiğim gibi, varsayılan olarak "performansı optimize etmek" - varsayılan olarak% 99 için iyidir. Sonuçları değiştirebileceği vakaların% 1'i, NEWID gibi yan etkileyici 'işlevler' açısından oldukça kolay anlaşılır ve 'düzeltilmesi' kolaydır (bunun sonucunda işlem harikası). Yeniden "performansı optimize etmek" için varsayılan bu, uzun süredir kurulmuş ve kabul edilmiştir. (Evet, derleyiciler tarafından geleneksel programlama dilleri için seçilen duruş değil, öyle olsun).
Yani, önerilerimiz:
a) Garanti edilmeyen zamanlama ve infaz sayısı semantiğine güvenmekten kaçının. b) NEWID () ifadesini tablo ifadelerinin derinliklerinde kullanmaktan kaçının. c) Belirli bir davranışı zorlamak için OPTION seçeneğini kullanın (işlem perf)
Umarım bu açıklama bu hatayı "düzeltmeyecek" olarak kapatma nedenlerimizi netleştirmemize yardımcı olur.
İlginçtir, AND NOT (s_guid = NEWID())
aynı yürütme planını verir
Bu, sorgu derlemesi sırasında çok erken olan normalleşmenin bir sonucudur. Her iki ifade de tam olarak aynı normalize formda derlenir, böylece aynı uygulama planı üretilir.