INNER JOIN sözdizimi, OUTER JOIN içinde sorgu sonuçlarının karşılaştırması


10

TLDR; 2 yürütme planına bakarsanız, hangisinin daha iyi olduğuna dair kolay bir cevap var mı? Amaçlı olarak dizin oluşturmadım, böylece neler olduğunu görmek daha kolay.

Farklı birleşim stilleri (yani iç içe ve geleneksel) arasındaki sorgu performansı farkını bulduğumuz önceki sorumun ardından , iç içe sözdiziminin de sorgunun davranışını değiştirdiğini fark ettim. Aşağıdaki 2 sorguyu düşünün.

SELECT  a.*, m.*, n.*
FROM    dbo.Autos a
LEFT JOIN dbo.Models m
  JOIN dbo.Manufacturers n  -- <-- Nested INNER JOIN
  ON n.ManufacturerID = m.ManufacturerID
ON m.ModelID = a.ModelID

resim açıklamasını buraya girin

Bu , Modeller tablosunda DEĞİL bir ModelID ile otomatik bir satır eklemek için üreticilerin birleştirme yapmak zorunda değildir .

resim açıklamasını buraya girin

Geleneksel sözdizimini kullanarak, İmalatları birleştirmeyi dış birleşim olarak değiştirmeliyiz, ancak ... ancak bu sorgu planını değiştirir.

SELECT a.*, m.*, n.*
FROM dbo.Autos a
LEFT JOIN dbo.Models m
ON m.ModelID = a.ModelID
LEFT JOIN dbo.Manufacturers n -- <-- Now LEFT OUTER JOIN
ON n.ManufacturerID = m.ManufacturerID

resim açıklamasını buraya girin

Yanıtlar:


12

2 yürütme planına bakarsanız, hangisinin daha iyi olduğuna dair kolay bir cevap var mı? Amaçlı olarak dizin oluşturmadım, böylece neler olduğunu görmek daha kolay.

İkinci planın tahmini maliyeti daha düşüktür, bu nedenle bu sınırlı anlamda 'daha iyidir'.

Veri kümeleri o kadar küçüktür ki, optimizer alternatiflere bakmak için fazla zaman harcamamıştır. Sorgunun ilk biçimi, hash join ve bir table spool kullanarak erken bir plan bulmak için olur. Bu planın tahmini maliyeti o kadar düşük ki, optimizer daha iyi bir şey aramaya zahmet etmiyor.

Sorgunun ikinci biçimi, arama işleminin başlarında yalnızca iç içe döngüler dış birleşimleri kullanarak bir plan bulmaktır ve yine iyileştirici, planın yeterince iyi olduğuna karar verir. Bu planın daha ucuz olduğu tahmin ediliyor.

Bununla birlikte (soru yorumlarında belirtildiği gibi) iki sorgu anlamsal olarak aynı değildir. Sonuçların veritabanınızın gelecekteki tüm olası durumları için her zaman aynı olacağını garanti ederseniz, bu sizin için önemli olmayabilir, ancak optimize edici bu varsayımı yapamaz. Her koşulda, yalnızca SQL tarafından belirtilen aynı sonuçları üreteceği garanti edilen planlar üretir .

İç içe sözdiziminin de sorgu davranışını değiştirdiğini fark ettim.

'İç içe sözdizimi', tüm ANSI birleştirme sözdizimi belirtiminin yalnızca bir yönüdür. Daha karmaşık birleştirme kalıpları için tam mantıksal belirtimi etkinleştirmek için, belirtim (isteğe bağlı) parantezlere ve FROMyan tümce alt sorgularına izin verir .

Sorgu parantez kullanılarak aynı ANSI sözdizimi kullanılarak yazılabilir :

SELECT
    A.*,
    M.*,
    N.* 
FROM dbo.Autos AS A
LEFT JOIN
(
    dbo.Manufacturers AS N
    JOIN dbo.Models AS M
        ON M.ManufacturerID = N.ManufacturerID
) ON M.ModelID = A.ModelID;

Bu şekilde mantık gereksinim soldan katılmak olduğunu açıkça göstermektedir Autosiçin sonuç iç birleştirme Manufacturersiçin Models. İsteğe bağlı parantezleri atlamak, 'iç içe' olarak adlandırdığınız formu verir:

SELECT
    A.*,
    M.*,
    N.* 
FROM dbo.Autos AS A
LEFT JOIN dbo.Manufacturers AS N
JOIN dbo.Models AS M
    ON M.ManufacturerID = N.ManufacturerID
    ON M.ModelID = A.ModelID;

Bu farklı bir sözdizimi değildir - yalnızca isteğe bağlı parantezleri atlayıp biraz yeniden biçimlendirir.

Martin'in belirttiği gibi, bu durumda mantıksal gereksinimi iç birleşimler ve ardından sağ dış birleşim kullanarak ifade etmek de mümkündür:

SELECT
    A.*,
    M.*,
    N.* 
FROM dbo.Manufacturers AS N
JOIN dbo.Models AS M
    ON M.ManufacturerID = N.ManufacturerID
RIGHT JOIN dbo.Autos AS A
    ON A.ModelID = M.ModelID;

Yukarıdaki üç sorgu formunun tümü aynı ANSI birleştirme sözdizimini kullanır. Her üçü de sağlanan veri seti ile aynı fiziksel uygulama planını üretmektedir:

Ortak yürütme planı

Önceki sorunuza verdiğim yanıtta da belirttiğim gibi, tam olarak aynı mantıksal gereksinimi ifade eden sorgular her zaman aynı yürütme planını üretmeyecektir. Hangi mantıksal sorgu formunu kullanmayı tercih edeceğiniz büyük ölçüde bir stil meselesidir. Genel olarak belirli bir stil ile 'daha iyi' sorgu planları arasında bir ilişki yoktur. Genellikle yeni sorgu gerçekten mantıksal olarak orijinaliyle aynı değilse belirli bir plan elde etmek için bir sorguyu yeniden yazma karşı öneriyoruz.

SQL standardı, FROMyan tümce sorgularına da izin verir , bu nedenle aynı sorgu belirtimini yazmanın başka bir yolu da şöyledir:

SELECT * 
FROM dbo.Autos AS A
LEFT JOIN
(
    SELECT
        N.ManufacturerID,
        ManufacturerName = N.Name,
        M.ModelID,
        ModelName = M.Name
    FROM dbo.Manufacturers AS N
    JOIN dbo.Models AS M
        ON M.ManufacturerID = N.ManufacturerID
) AS R1
    ON R1.ModelID = A.ModelID;

Geleneksel sözdizimini kullanarak, birleşimi `` Üreticiler dış birleşim olarak değiştirmeliyiz, öyle ... ama bu sorgu planını değiştiriyor.

Bu muhtemelen teknik olarak geçerli bir alternatif değildir ve bu durumda sorgu anlamını değiştirir (ancak bkz ypercube 'ın comment sorunuza).

ANSI birleştirme sözdizimindeki (isteğe bağlı) parantezler, bunun gibi daha karmaşık birleştirme gereksinimleri için tam olarak vardır, bu nedenle bunları gerektiğinde kullanmaktan korkmamalısınız.

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.