ON ve NEREDE endeks performansı


26

İki masam var

@T1 TABLE
(
    Id INT,
    Date DATETIME
)

@T2 TABLE
(
    Id INT,
    Date DATETIME
)

Bu tablolarda kümelenmemiş bir dizin var (Id, Date)

Ve bu tablolara katılırım

SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON 
    t1.Id = t2.Id
WHERE 
    t1.Date <= GETDATE()
    AND
    t2.Date <= GETDATE()

Bu ayrıca olarak da yazılabilir.

SELECT *
FROM T1 AS t1
INNER JOIN T2 AS t2
ON 
    t1.Id = t2.Id
    AND
    t1.Date <= GETDATE()
    AND
    t2.Date <= GETDATE()

Sorum şu, bu iki sorgudan hangisi daha iyi performans sağlıyor ve neden? Yoksa eşit mi?


1
Gerçekten, tüm alanları kapsayan kümelenmiş bir dizini olan ve kümelenmiş bir dizini olmayan bir değişken var mı? ya da sadece bir basitleştirme mi?
Remus Rusanu,

1
Bu aşırı bir sadeleştirme
Erik Bergstedt

Yanıtlar:


32

Performans aynı olacak. İyileştirici bunu tanır ve aynı planı oluşturur.

Öte yandan, eşit olduklarını söyleyemem. İlk form söz konusu çok daha okunabilir ve genel olarak beklenen olduğunu.

Eldeki bazı tabloları kullanarak bir örnek için, yürütme planının, sorguyu nasıl yazdığımdan bağımsız olarak tamamen aynı olduğunu görebilirsiniz.

Kendi tablolarınız ve veri kümeniz için sorgu planlarını belirleyebilmelisiniz, böylece durumunuzda neler olduğunu görebilirsiniz.

SELECT * FROM salestable , custtable 
WHERE salestable.custaccount = custtable.accountnum 
AND salestable.dataareaid = custtable.dataareaid

SELECT * FROM salestable 
JOIN  custtable 
ON salestable.custaccount = custtable.accountnum 
AND salestable.dataareaid = custtable.dataareaid

SELECT * FROM salestable JOIN custtable 
ON salestable.custaccount = custtable.accountnum 
WHERE salestable.dataareaid = custtable.dataareaid

Bu icra planlarını verir

görüntü tanımını buraya girin


Kabul ediyorum, ilk formun okunması daha kolay ve bu yüzden eşit olmalarına yardımcı oldum. Bu formu yalnızca gelecekte kullanacağım.
Erik Bergstedt

@ErikBergstedt Cevabımı düzelttim, kendi veri setiniz ve tablo yapınız için bunu uygulama planlarına baktığınızda kolayca doğrulayabilmelisiniz
Tom V - Team Monica

Evet yaptım. Teşekkür ederim. Mevcut bir cevap bulamadığım için sadece ikinci bir görüş arıyordum.
Erik Bergstedt,

Not: SADECE eşittir onlar bir INNER JOIN. Bir içine atmak OUTER JOINo zaman kesinlikle aynı değildir.
Kenneth Fisher

22

Anlamsal olarak özdeştirler ve iyimser bu gerçeği tanımakta ve aynı planlar oluşturmakta zorlanmamalıdır.

Her iki tabloyu da gösteren ONkoşulları ve içindeki tek bir tabloyu gösteren koşulları koyma eğilimindeyim WHERE.

İçin OUTER JOINSkoşulları hareketli ancak anlamsal etkileyebilir.


7

Basit durumlarda, aynı olacaktır. Ancak, birkaç birleşme ile çok karmaşık sorguların önemli ölçüde farklı planları olduğunu gördüm. Üzerinde çalıştığım yeni bir çalışma, yaklaşık 20 farklı masaya katılan 6 milyona yakın satırı olan bir masa ile başladı. Bu masaya yalnızca ilk birleşme bir birleştirme idi, diğerleri dış ek birleştirme bıraktı. Fıkradaki filtre, şunun gibi bir parametreye dönüştürüldü:

WHERE table1.begindate >= @startdate AND table1.enddate < @enddate 

Bu filtre daha önce yerine daha sonra planda kullanıldı. Bu koşulları ilk iç birleşime taşıdığımda, sonuç kümesini sınırlamak için filtre uygulamanın başında uygulandığında plan çarpıcı bir şekilde değişti ve CPU ve geçen zamanım yaklaşık% 310 düştü. Bu nedenle, birçok SQL Server sorusunda olduğu gibi, buna bağlı olarak değişir.


2
Cevabınız diğerleriyle çelişiyor gibi göründüğü için daha fazla ayrıntı ekleyebilir misiniz - belki de uygulama planı şemalarının ekran görüntüleri -?
Kenny Evitt,

2
Plan, optimizasyon zaman aşımını gösterdi mi?
Martin Smith,

CPU yükü% 100'den daha fazla nasıl düşebilir?
Michael Green,

2

Genel olarak, filtreleri koyduğunuz yer fark yaratır.
Tom V, Doktor’un sorguların aynı olduğunu ve aynı planla geldiğini fark edeceğini söylese de, bu her zaman doğru değildir. Hangi SQL sürümünde olduğunuza, sorgunuzun ne kadar karmaşık olduğuna ve Doktor'un sorgunun ne kadar önemli olduğunu belirlediği toplu iş için ne kadar önemli olduğuna bağlıdır.

Optimize Edici, partinin bu kısmının en iyi planın ortaya çıkmasına izin vermek için yeterli zaman harcayamayacağına karar verebilir. Genelde, sorgunun WHERE yan tümcesi yerine ON cümlesi üzerinde çalışması gereken verilerin miktarını azaltan koşullar koyarsanız daha iyi performans elde edersiniz (eğer mümkünse, bunu bir dış birleştirmeyle yapmanız kartezyen bir ürünle sonuçlanacaktır. .)

SQL Developer'ın WHERE yan tümcesinde filtreleri tespit etmesi biraz daha kolay, ancak ON yan tümcesinde filtrelerin çalışmasının çalışma saatleri dışında kesildiği bazı büyük masalarda çalıştım.

Bu nedenle, tümce, sorgunun okuyacağı satır sayısını büyük ölçüde azaltma potansiyeline sahipse, Optimize Edici'nin daha iyi bir plan seçmesine yardımcı olmak için her zaman AÇIK cümlesi içerisine koyacağım.


1

Sıradan koşullar altında, filtre koşulları NEREDE veya JOİN yan tümcelerinde belirtilebilir. OUTER JOIN önceliği etkilenemedikçe (aşağıya bakınız) veya filtre bu tabloya çok özel değilse (örn. Tablodaki belirli bir satır alt kümesini belirlemek için TYPE = 12) filtreleri WHERE altına yerleştirme eğilimindeyim.

Öte yandan, hem ON hem de WHERE cümleleri birleştirme koşullarını (filtre koşullarının aksine) belirtmek için kullanılabilir. Yalnızca INNER birleşimlerini kullandığınız sürece, normal koşullarda hangisini kullandığınızın önemi yoktur.

Ancak OUTER birleşimlerini kullanıyorsanız, çok fazla fark yaratabilir. Örneğin, iki tablo arasında (t1 ve t2) bir OUTER JOIN belirlerseniz, ancak daha sonra, NERED deyiminde, tablolar arasında bir eqijoin ilişkisi belirtmeye devam ederseniz (örneğin, t1.col = t2.col), OUTER birleştirmesini bir INNER toplantısına dönüştürdü! Bunun nedeni, bir ON yan tümcesini kullanmadan bir equijoin (veya belki de OUTER birleşimini, sürümüne bağlı olarak, kullanımdan kaldırılmış * = sözdizimini kullanarak) belirtmek için kullanılabildiğinden ve WHERE tablolar arasında bir iç denkliği gösterdiğinde, bir OUTER geçersiz kılar. JOIN (varsa).

Asıl soru, birleşme türünün sıklıkla bir sorun olmaması gerektiği, ancak bir birleşme bir filtre olarak da rol oynayabileceği filtreler hakkındaydı ve bu durumlarda birleştirme koşulunun yerleştirilmesi kesinlikle önemli olabilir.


-1

INNER JOINs ile bu bir stil sorunudur.

Ancak, OUTER JOIN'lerle çok daha ilginç hale geliyor. OUTER JOIN sorguları ile hem ON hem de WHERE deyimindeki koşullar arasındaki farkları keşfetmelisiniz. Sonuç kümesi her zaman aynı değildir. Mesela

OUTER JOIN dbo.x ON a.ID = x.ID ... WHERE x.SomeField IS NOT NULL

aynı

INNER JOIN dbo.x ON a.ID = x.ID AND x.SomeField IS NOT NULL

8
Sonuç farklıysa (elbette ki), performans karşılaştırmanın amacı nedir?
ypercubeᵀᴹ
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.