İyi, Kötü veya Kayıtsız: NEREDE 1 = 1


14

Reddit'te bu soru göz önüne alındığında , sorunun sorgunun neresinde olduğunu göstermek için sorguyu temizledim. İlk önce virgül kullanıyorum ve WHERE 1=1sorguları değiştirmeyi kolaylaştırmak için sorgularım genellikle şöyle:

SELECT 
     C.CompanyName
    ,O.ShippedDate
    ,OD.UnitPrice
    ,P.ProductName
FROM 
               Customers       as C
    INNER JOIN Orders          as O  ON C.CustomerID = O.CustomerID
    INNER JOIN [Order Details] as OD ON O.OrderID    = OD.OrderID
    INNER JOIN Products        as P  ON P.ProductID  = OD.ProductID
Where 1=1
--  AND O.ShippedDate Between '4/1/2008' And '4/30/2008'
    And P.productname = 'TOFU'
Order By C.CompanyName

Birisi temel olarak 1 = 1'in genellikle tembel ve performans için kötü olduğunu söyledi .

Ben "erken optimize etmek" istemiyorum göz önüne alındığında - Ben iyi uygulamaları takip etmek istiyorum. Daha önce sorgu planlarına baktım, ancak genellikle sadece daha hızlı çalışmasını sağlamak için hangi dizinleri ekleyebileceğimi (veya ayarlayabildiğimi) öğrenmek için.

O zaman soru gerçekten ... Where 1=1kötü şeylerin olmasına neden oluyor mu? Ve eğer öyleyse, nasıl söyleyebilirim?

Küçük Düzenleme: Daima 1=1optimize edilebileceğini veya en azından ihmal edilebilir olacağını da varsaydım . "Goto's Evil" veya "Prematüre Optimizasyon ..." veya diğer varsayılan gerçekler gibi bir mantrayı sorgulamak asla acıtmaz. 1=1 ANDSorgu planlarını gerçekçi bir şekilde etkileyip etkilemeyeceğinden emin değildi. Alt sorgularda ne olacak? CTE'ler? Prosedürler?

İhtiyaç duyulmadıkça optimizasyon yapacak biri değilim ... ama aslında "kötü" bir şey yapıyorsam, etkileri en aza indirmek veya uygulanabilir olduğu yerde değiştirmek istiyorum.


2
Hayır. Optimize edicinin yedekli koşulu kaldırması için birkaç mikrosaniye dışında. Tarih değişmezlerinin belirsiz olmamasına odaklansanız iyi olur.
ypercubeᵀᴹ

@Ypercube'in dediği gibi, hiçbir fark yaratmaz. Sorgu
iyileştirici

4
Reddit'te okuduğunuz her şeye inanmayın. Lütfen.
Aaron Bertrand

1
@AaronBertrand İlk elden deneyene kadar her şeyi bir tuz tanesi ile alıyorum. Hala kulağa mantıklı gelen bir soru alacağım ve özellikle günlük işimi etkilediğinde herhangi bir gerçek olup olmadığını göreceğim.
WernerCD

4
Tuz taneleri var, o zaman ofis binasının üzerine dökülen tüm okyanusun tuz içeriği var: P
Philᵀᴹ

Yanıtlar:


13

SQL Server ayrıştırıcıoptimizer, sorgudan totolojik ifadeleri ortadan kaldıran "Sabit Katlanır" özelliğine sahiptir.
Yürütme planına bakarsanız, tahminlerde hiçbir yerde ifadenin görünmediğini göremezsiniz. Bu, sabit katlamanın yine de bu ve diğer nedenlerle derleme zamanında gerçekleştirildiğini ve sorgu performansı üzerinde hiçbir etkisi olmadığını gösterir.

Daha fazla bilgi için bkz. Kardinalite Tahmini Sırasında Sabit Katlama ve İfade Değerlendirmesi .


Muhtemelen derlenmiştir, çünkü bu alanların birleştirilmesini bilinen bir örüntüdür.
jcolebrand

Hayır, derlendi çünkü totolojik. 2736 = 2736 ile aynı şekilde çalışır, ki bu 1 = 1 gibi olağan değildir. Aynı şey çelişkiler için de geçerlidir. Bu durumda özelliğe "Çelişki algılama" adı verilir.
spaghettidba

"Bilinen patern" in hangi kısmı "1 = 1" olmalıdır?
jcolebrand

9

Gereksiz yüklemin eklenmesi SQL Server'da fark yaratabilir.

Aşağıdaki yürütme planlarında @1, birinci planda 'foo'ikinci plandaki değişmezi fark edin .

resim açıklamasını buraya girin

Bu, SQL Server'ın yürütme planının yeniden kullanılmasını teşvik etmek için basit parametrelendirme için ilk sorguyu düşündüğünü gösterir - ancak iki sabitin karşılaştırılması, bunun ikinci durumda olmasını engeller.

Basit parametrelendirmeyi (daha önce otomatik parametrelendirme olarak bilinirdi) önleyen koşulların bir listesi, Planlı Önbelleğe Alma Microsoft Teknik Belgeleri Ek A'da bulunabilir:

basit parametrelendirme genellikle yine de güvenmeniz gereken bir şey değildir. Sorgularınızı açıkça parametrelendirmek çok daha iyidir.


4

Herhangi bir modern RDBMS'de (Oracle, Microsoft SQL Server ve PostgreSQL dahil - bunlardan eminim) bunun performans üzerinde hiçbir etkisi olmayacaktır.

Birisinin belirttiği gibi, bu sadece sorgu planlama aşamasını etkileyecektir. Bu nedenle, fark yalnızca, böyle bir veri döndürmeyen basit bir sorgunun binlerce yinelemesini çalıştırdığınızda görünür olacaktır:

SELECT 1 FROM empty_table; -- run this 10 000 times.

SELECT 1 FROM empty_table WHERE 1=1; -- run this 10 000 times and compare.

Benim için, PostgreSQL 9.0'da, bu sadece 10000 yineleme ile görülebilir:

filip@srv:~$ pgquerybench.pl -h /var/run/postgresql/ -q "select 1 from never where 1=1" -q "select 1 from never" -i 10000
Iterations: 10000
Query:   select 1 from never where 1=1
Total:   2.952 s
Average: 0.295 ms
Query:   select 1 from never
Total:   2.850 s
Average: 0.285 ms

0

Cursor_sharing veritabanı parametresini kullandığınızda bu, Oracle için "sorun" olabilir. Bu "zorla" olarak ayarlandığında, tüm SQL ifadelerini değiştirir. Sorgulardaki tüm "sabitler" bind değişkenleriyle değiştirilir (1 =>: SYS_0 gibi).

Bu seçenek bazı tembel geliştiricilerle başa çıkmak için tanıtıldı. Öte yandan diğer tembel geliştiricilere de zarar verebilir. Ancak risk çok yüksek değil. 11g'den beri değişken gözetleme özelliğine sahiptir.


Eğer netleştirmek Can "11g beri bağlamak değişken özelliği atmayı oldu." anlamına geliyor?
ypercubeᵀᴹ

@ypercube "Bağlama değişkeni gözetleme", iyileştiricinin bağlanma değişkenlerinin gerçek değerlerini gözlemleyeceği ve sorgu yürütme planını yeniden değerlendirmek ve muhtemelen yeniden oluşturmak için veri istatistiklerini kullanacağı anlamına gelir. Veri istatistiklerine bağlı olmadığı için, göz atmanın tartışılan yapı üzerinde herhangi bir etkisi olacağından şüpheliyim.
mustaccio
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.