it-swarm.asia

JOIN anahtar kelimesini kullanıp kullanmadığınız

Aşağıdaki SQL sorguları aynıdır:

SELECT column1, column2
FROM table1, table2
WHERE table1.id = table2.id;

SELECT column1, column2
FROM table1 JOIN table2 
ON table1.id = table2.id;

Ve kesinlikle şimdiye kadar denedim her DBMS aynı sorgu planları sonuçlanır.

Ama sık sık, birinin kesinlikle diğerinden daha iyi olduğu fikrini okuyorum ya da duyuyorum. Doğal olarak, bu iddialar hiçbir zaman bir açıklama ile kanıtlanamaz.

Çalıştığım yerde, ikinci sürüm diğer geliştiricilerin çoğunluğu tarafından tercih ediliyor gibi görünüyor ve bu yüzden de sürprizleri en aza indirmek için bu stile doğru yöneliyorum. Ama kalbimde, ilkini gerçekten düşünüyorum (çünkü başlangıçta böyle öğrendim).

Bu formlardan biri nesnel olarak diğerinden daha mı iyi? Değilse, birini diğerinin üzerinde kullanmanın nedenleri ne olurdu?

İkinci formun daha iyi olduğunu düşünüyorum. Bunun nedeni, bunu nasıl öğrendiğimi itiraf edeceğim, ancak somut bir nedenim var - endişelerin ayrılması. Nerede cümlesindeki tablolara katılmak için kullandığınız alanları koymak, sorguları anlamada zorluklara neden olabilir.

Örneğin, aşağıdaki sorguyu alın:

select *
from table1, table2, table3, table4
where table1.id = table2.id
and table2.id = table3.id
and table3.id = table4.id
and table1.column1 = 'Value 1'

Yukarıdaki sorgu tek bir alanda birleştirilen tablo birleştirme koşulları ve gerçek iş mantığı koşullarına sahiptir. Büyük bir sorgu ile, bunu anlamak çok zor olabilir.

Ancak, şimdi bu kodu alın:

select *
from table1 join table2 on table1.id = table2.id
join table3 on table2.id = table3.id
join table4 on table3.id = table4.id
where table1.column1 = 'Value 1'

Bu durumda, tablolarla veya bunların ilişkisiyle ilgili olan her şeyin tümü yan tümceden izole edilirken, sorgu kısıtlaması için gerçek iş mantığı nerede yan tümcesinde bulunur. Özellikle daha büyük sorgular için bunun çok daha anlaşılır olduğunu düşünüyorum.

62
Dustin Wilhelmi

Birleştirme sözdizimi 1992'de eski virgül sözdiziminin yerini almıştır. Şu anda virgül sözdizimi ile kod yazmak için hiçbir neden yoktur. Hiçbir şey kazanmazsınız ve açık sözdiziminde sahip olmadığınız bazı sorunlara maruz kalırsınız.

İlk etapta, daha karmaşık sorgular elde ettiğinizde, bir durum koşulu eksik olarak yanlışlıkla çapraz birleştirme yapmak çok kolaydır. Bu, bir sözdizimi hatası alacağınız için açık birleştirme sözdiziminin olmasını engelleyebileceği bir şeydir.

Çapraz bir katılma niyetindeyseniz, açık birleştirme sözdizimi, örtük sözdiziminde, bakım yapan birisinin where yan tümcesini eklemeyi unuttuğunuzu varsayabilir.

Sonra örtük sözdizimini kullanarak en azından bazı dbs sorunlu olan sol ve sağ birleşim sorunu var. Bunlar SQL Server'da kullanımdan kaldırılmıştır ve aslında eski sürümlerde bile doğru sonuçları düzgün bir şekilde döndürmezler. Dış birleştirme gerektiren hiçbir sorgu SQL Server'da örtük sözdizimi içermemelidir.

Ayrıca, burada ve insanlar örtülü ve açık birleşimleri karıştırdıklarında (örneğin sol birleştirme eklerken) yanlış sonuçların ortaya çıktığı diğer sorularda gördüm, bu yüzden bunları karıştırmak kötü bir fikirdir.

Son olarak, örtülü birleşimleri kullanan birçok kişi birleşimleri gerçekten anlamıyor. Bu, bir veritabanını etkin bir şekilde sorgulamak için kritik bir anlayıştır.

40
HLGEM

Ha. PostgreSQL belgelerine bakarken, kendi soruma olası bir cevap buldum. Bu sayfanın açıkladıklarını özetlemek için, sonuçta elde edilen sorgu hala aynıdır, ancak optimize edicinin dikkate alması gereken plan sayısı , birleştirmelerin sayısıyla katlanarak artar.

Bu tür yaklaşık altı birleştirmeden sonra, sayı o kadar büyüktür ki, sorguyu planlama süresi fark edilebilir ve yaklaşık ondan sonra, optimize edici planların kapsamlı bir aramasından olasılıklı bir aramaya geçecek ve optimal plana ulaşamayabilir .

Bir çalışma zamanı parametresi ayarlayarak, planlayıcıdan açıkça belirtilen iç ve çapraz eklemleri örtülü birleşimlerden farklı şekilde ele almasını, bunları planın üst kısmına zorlamasını ve diğer seçenekleri keşfetmemesini isteyebilirsiniz.

Not, varsayılan davranış her iki durumda da aynıdır ve alternatif planlar elde etmenin farklı bir sonuç elde etmek için dbms'in içselleri ve söz konusu tabloların özellikleri hakkında bilgi gerektirmesi gerekir.

İşte bunun set teorisi görünümü:

İki (veya daha fazla) tablo adını ayırmak için virgül kullandığınız zaman kartezyen üründür. 'Sol' tablonun her satırı, sağ tablonun satırıyla "eşleştirilir" (birleştirilir).

Şimdi nerede deyimine bir şey yazarsanız, bu 'birleştirmeye' hangi satırları hangi satırlarla 'birleştireceklerini' söyleyen bir koşul koymak gibidir.

Bu aslında satırları "birleştiriyor" ve dolayısıyla daha okunabilir bir sözdizimi sağlamaya yardımcı olan ve 'gerçekten' bazı ortak değerlere katılmak istediğinizden daha anlaşılır olan join anahtar kelimesi. @Dustin'in yukarıda açıkladığı şeye benzer.

Şimdi, her DBMS akıllıdır, yani önce kartezyen ürünü hesaplamaz ve sonra verileri filtreler (son derece israf), ancak bunu sorgu yapısına göre yapar. Düşünebileceğim tek şey, 'katılmasını' istediğinde, katılma etkinliğini açık hale getirmek gibi görünüyor ve muhtemelen kodu daha hızlı çalıştırmaya yardımcı oluyor (ne kadar? Profil ve görmeniz gerekecek) ama virgülle ayrılmış durumda, optimum stratejiyi belirlemek için biraz zamana ihtiyaç vardır. Yanlış olabilirim, ama sadece nasıl kodlayacağına dair eğitimli bir tahmin yapıyorum ...

8
PhD

Bu durum için JOIN deyimlerini kullanmak genellikle daha iyi olur.

Gelecekte, ifadenin bir INNER JOIN'dan bir OUTER JOIN'a değiştirilmesini gerektiren bir durum ortaya çıkarsa, bunun ikinci ifade ile yapılması çok daha kolay olacaktır.

5
Britt Wescott

Herhangi bir RDBMS, onları yürütme açısından aynı şey haline getirecektir. Daha okunaklı ve etkileyici olup olmadığı anlaşılır.

JOIN'i kullanarak birleştirme eşleşmesinin ne olduğunu ve gerçek seçimin ne olduğunu net bir şekilde görün.

select name, deptname
from people p, departments d
where p.deptid = d.id and p.is_temp = 'Y'

vs.

select name, deptname
from people p
    inner join departments d on p.deptid = d.id
where p.is_temp = 'Y'

İkinci durum, birleştirme koşulu ve hangisinin seçim kriteri olduğunu hemen ortaya koymaktadır.

3
Andy Lester

Ben sadece bir kez optimizasyon farklı bir dizi iki sonuç gördük ve eğer bellek hizmet eğer gerçekten kıllı bir sorgu ms-sql2k oldu. Bu örnekte * = ile kullanılan eski form yaklaşık 4 kat daha hızlı performans ile sonuçlanmıştır. Microsoft teknoloji adamlarımız dahil hiç kimse nedenini açıklayamadı. MS adamları bunu bir hata olarak etiketlediler. Bir daha hiç görmedim.

Çoğu RDBMS, tam cartesianları yapamayacak kadar akıllı olduğu için, onu kullanmamayı düşünebilmemin en büyük nedeni (amortismana tabi tutulmasının yanı sıra), 30-35 yaşın altındaki insanların çoğunun eski formdan önce ve karşılaştıklarında çok kaybolurlar.

1
Bill