Birleştirme, çalışma zamanında nerede deyimine göre optimize edilmiş mi?


14

Böyle bir sorgu yazdığımda ...

select *
from table1 t1
join table2 t2
on t1.id = t2.id

SQL optimizer, doğru terim olup olmadığından emin değil, bunu çevirmek ...

select *
from table1 t1, table2 t2
where t1.id = t2.id

Temel olarak, SQL Server'da Join deyimi sql yazmak için daha kolay bir yol mudur? Yoksa aslında çalışma zamanında mı kullanılıyor?

Düzenleme: Neredeyse her zaman ve neredeyse her zaman Katıl sözdizimini kullanacağım. Sadece ne olacağını merak ediyorum.


1
"Neredeyse" hakkında ayrıntı verebilir misiniz? Eski stil sözdizimini ne zaman kullanırsınız ve neden?
Aaron Bertrand

2
Eğer bir (kaldırıldı) eklerseniz bir fark yaratıyor biri kenar durumdur GROUP BY ALLiçinde
Martin Smith

@MartinSmith bilerek kullanan GROUP BY ALLvar mı? :-)
Aaron Bertrand

@AaronBertrand - Şüpheliyim! Hiç kimsenin onu kullandığını gördüğümü sanmıyorum.
Martin Smith

Yanıtlar:


20

Bunlar içsel olarak aynı şeye çöküyor. İlki her zaman yazmanız gereken . Daha da önemlisi, neden önemlidir? Yürütme planı ve performans açısından özdeştirler (bunu bozmadığınız varsayılırsa, tembel, eski stil sözdizimi ile daha kolay).

İşte AdventureWorks kullanarak hiçbir şeyin olmadığını CROSS JOINve filterdevam ettiğini gösteren bir kanıt .


Açık katılım:

resim açıklamasını buraya girin


Örtük birleştirme:

resim açıklamasını buraya girin


Bak anne! Özdeş planlar, özdeş sonuçlar, hiçbir yerde çapraz birleşme veya filtreler görülmez.

(Açıklık olması açısından, SELECTher iki durumda da operatör üzerindeki uyarı, her iki durumda birleştirme ile ilgisi olmayan, kardinaliteyi etkileyen örtük bir dönüştürmedir.)


20

Kesin olarak, sorgu optimize edici girişinde iki form arasında bir fark vardır:

-- Input tree (ISO-89)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM 
    Production.Product AS p,
    Production.ProductInventory AS inv
WHERE
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

ISO-89 giriş ağacı

-- Input tree (ISO-92)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM Production.Product AS p
JOIN Production.ProductInventory AS inv ON
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

ISO-92 giriş ağacı

Gördüğünüz gibi, ONmadde yüklemi modern sözdizimini kullanarak birleştirmeye sıkı sıkıya bağlıdır. Eski sözdiziminde, bir ilişkisel seçim (bir satır filtresi) ardından mantıksal bir çapraz birleştirme vardır.

Sorgu iyileştirici, neredeyse her zaman ilişkisel seçimi en iyileştirme sırasında birleştirmeye daraltır, yani iki form büyük olasılıkla eşdeğer sorgu planları üretecektir, ancak gerçek bir garanti yoktur.


4

İç birleşim için değiştirilebilirler, ancak Dış Birleşimler için farklı anlamları vardır - ON eşleşir ve NEREDE basit filtreleme. Bu yüzden ON üzerinde doğru JOIN sözdizimi eşleşmesine bağlı kalmak daha iyidir.


4

Tamam, merak ettim bu yüzden bir test yaptım. Aşağıdakiler için gerçek yürütme planlarım var.

select * 
from sys.database_principals prin, sys.database_permissions perm
WHERE prin.principal_id = perm.grantee_principal_id

ve

select * 
from sys.database_principals prin
JOIN sys.database_permissions perm
    ON prin.principal_id = perm.grantee_principal_id

Onları nesneye göre karşılaştırdım ve aynılardı. En azından çok basit bir örnek için, aynı şeye çıktılar. Ayrıca istatistikler IO ve zaman kontrol ve aynı şey olacak kadar yakın.

Bununla birlikte, JOINsözdizimini kullanmalısınız çünkü okumak daha kolaydır ve özellikle karmaşık sorgularda hata yapma olasılığınız daha düşüktür. Ve birleşimler için *=/ =*sözdizimi OUTERSQL-Server 2005'ten beri kaldırılmıştır.

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.