İç katılmak vs nerede


257

Arasında performans farkı (kehanet içinde) var mı

Select * from Table1 T1 
Inner Join Table2 T2 On T1.ID = T2.ID

Ve

Select * from Table1 T1, Table2 T2 
Where T1.ID = T2.ID

?


1
sadece kayıt için, sorguların yalnızca bir birleşimden bir nerede cümlesine
geçerek

12
@BlackTigerX: Farklı sonuçlar? Herhangi bir dış birleşim var mı? Çünkü maddeye inner join ... oneşdeğer birleştirme ölçütleri koymaya karşı farklı sonuçların nasıl olacağını göremiyorum where.
Shannon Kıdem

veritabanının eski sürümünde mevcut değiljoin
MajidTaheri

2
@MajidTaheri: Oracle sürümünün kaç yaşında bahsediyorsunuz? Oracle tarafından desteklenen tüm sürümler JOIN gösterimini destekler.
Jonathan Leffler

Önemsiz vakalara dayanan genel cevaplara veya en iyi uygulamalara dikkat edin. Birden fazla AND'd koşulu içeren cümlelerin bulunduğu daha karmaşık bir "yeniden eşleşme" görmek ister misiniz? En azından SQL Server'da bir geçiş noktası var.
crokusek

Yanıtlar:


195

Hayır! Aynı yürütme planı için şu iki tabloya bakın:

CREATE TABLE table1 (
  id INT,
  name VARCHAR(20)
);

CREATE TABLE table2 (
  id INT,
  name VARCHAR(20)
);

İç birleştirmeyi kullanan sorgunun yürütme planı:

-- with inner join

EXPLAIN PLAN FOR
SELECT * FROM table1 t1
INNER JOIN table2 t2 ON t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

Ve bir WHERE yan tümcesi kullanarak sorgu yürütme planı.

-- with where clause

EXPLAIN PLAN FOR
SELECT * FROM table1 t1, table2 t2
WHERE t1.id = t2.id;

SELECT *
FROM TABLE (DBMS_XPLAN.DISPLAY);

-- 0 select statement
-- 1 hash join (access("T1"."ID"="T2"."ID"))
-- 2 table access full table1
-- 3 table access full table2

4
Gerçekten Oracle bu konuda söyleyerek resmi belgeler olup olmadığını görmek istiyorum
4 Bırakın Kapak

68

Sorgu iyileştirici işini doğru yapıyorsa, bu sorgular arasında fark olmamalıdır. Aynı istenen sonucu belirtmenin sadece iki yoludur.


22
Evet, performans aynı olmalı. Ancak SELECT * Table1, Table2 NEREDEN ... sözdizimi kötüdür!
Joel Coehoorn

2
INNER JOINS için SQL-92 sözdiziminden daha kolay anlaşılır buluyorum. Kilometreniz değişebilir.
Craig Trader

25
WHERE sözdiziminin okunmasını INNER JION'dan daha kolay buluyorum - sanırım Vegemite gibi. Dünyadaki çoğu insan muhtemelen iğrenç buluyor, ancak çocuklar onu sevdi.
ScottCher

3
Vegemite gerçekten kötü, ama sonra tekrar hurdaya bayılıyorum. Git şekil.
StingyJack

2
@Darryl Sanırım JOINtabloları birleştirme koşulu, WHEREmaddede "bir yer" yerine hemen orada tanımlandığından , s'nin daha kolay olduğunu düşünüyorum . Tabloların birbiriyle nasıl ilişkilendiğini (örneğin ) tanımlamak yerine WHERE, veri kümesini (örneğin WHERE DATE > (SYSDATE - 1)) sınırlamak için yan tümceyi ayırmayı tercih ederim WHERE T1.ID = T2.ID. Söz konusu örnek gibi küçük bir tablo için çok az fark yaratır, ancak birkaç tablo ve birkaç koşul içeren büyük sorgular için, sorguyu daha kolay anlaşılmasını sağlar.
HayaliHuman072889

61

Tam olarak aynı olmalılar. Ancak, bir kodlama uygulaması olarak Join'i görmeyi tercih ederim. Niyetinizi açıkça ifade ediyor,


8
Katılıyorum. Özellikle birden çok tabloya katılıyorsanız, açık birleştirme yapıyorsanız belirli bir ifadeyi ayrıştırmak çok daha kolaydır.
Paul Morie

13
Aslında. Birleştirmeler, iki veri kümesi arasındaki anlamsal bir ilişkiyi gösterir, ancak burada filtrelenmiş bir küme önerilir. +1
EightyOne Unite

26

Kullanmak JOIN, kodu kendi kendini açıklayıcı olduğundan okumayı kolaylaştırır.

Hız farkı yok ( yeni test ettim ) ve uygulama planı aynı.


Teşekkür ederim. Bu iki yöntem arasında hız sıkıştırma arıyordum.
Farhad Navayazdan

14

Oracle hakkında bilmiyorum ama eski sözdiziminin SQL Server'da kullanımdan kaldırıldığını ve sonunda kaybolacağını biliyorum. Yeni bir sorguda bu eski sözdizimini kullanmadan önce Oracle'ın onunla ne yapmayı planladığını kontrol ederim.

Birleştirme ölçütlerinin diğer gerekli durumlarda koşullarla karıştırılması yerine daha yeni sözdizimini tercih ederim. Daha yeni sözdiziminde birleştirmeyi neyin oluşturduğu ve başka hangi koşulların uygulandığı çok daha açıktır. Böyle kısa bir sorguda gerçekten büyük bir sorun değil, ancak daha karmaşık bir sorgunuz olduğunda çok daha kafa karıştırıcı oluyor. İnsanlar temel sorguları öğrendiklerinden, karmaşık bir sorguda ihtiyaç duymadan önce birleştirme sözdizimini kullanmayı öğrenmeyi tercih ederim.

Ve yine Oracle'ı özellikle bilmiyorum, ancak eski stil sol birleştirmenin SQL Server sürümünün SQL Server 2000'de bile kusurlu olduğunu ve tutarsız sonuçlar verdiğini (bazen sol birleştirme bazen çapraz bir birleşim) biliyorum, bu yüzden asla Kullanılmış. Umarım Oracle aynı sorunu yaşamaz, ancak kesinlikle sol ve sağ birleşimler eski sözdiziminde düzgün bir şekilde ifade etmek çok daha zor olabilir.

Ayrıca, ANSII standart birleşimlerini kullanan geliştiricilerin bir birleştirmenin ne olduğunu ve elde etmek açısından ne anlama geldiğini daha iyi anlama eğiliminde olduğu benim deneyimim oldu (ve bu kesinlikle kişisel bir görüş, farklı bir deneyime sahip olabilirsiniz). veritabanı dışında veri. Bunun iyi bir veritabanı anlayışına sahip insanların çoğunun daha karmaşık sorgular yazma eğiliminde olduğuna inanıyorum ve bu eski tarzdan daha ANSII Standardı kullanarak sürdürmek çok daha kolay gibi görünüyor.


1
Amin kardeşim. JOINERS ile aşağı !!
ScottCher

14

[Bonus puan için ...]

JOIN sözdizimini kullanmak, bir satırda yer alan birleştirmeyi daha kolay yorumlamanıza olanak tanır. Bu olabilir , karmaşık sorgu hata ayıklama durumlarda yararlı olabilmektedir

Herkesin söylediği gibi, işlevsel olarak aynıdırlar, ancak JOIN bir niyet beyanından daha açıktır. Bu nedenle olabilir o belirli durumlarda geçerli oracle versiyonları (Ben eğer hiçbir fikrim yok) ya sorgu optimize edici yardımcı olabilir Oracle (kimse bir fikrin vardır) gelecekteki sürümlerinde sorgu optimize edici yardımcı, ya da olabilir eğer yardımcı veritabanı sağlayıcısını değiştirirsiniz.


2
Veya ... INNER JOINS'i LEFT JOINS olarak kolayca değiştirin, böylece hangi birleştirmenin beklenen satırları kaçırmanıza neden olduğunu görebilirsiniz. Bir kerede tüm sorguyu yaptığım için bunu yapıyorum. INNER JOINS'e yorum yaparsanız, bir eleme işlemi yapmanız gerekir. Daha uzun sürer. Ancak +1 sizin için çünkü bu, okunabilirlik dışında INNER JOINS'in en sevdiğim nedenlerinden biri!
Matthew McPeak

13

Mantıksal olarak aynıdırlar, ancak ANSI sözdizimini benimseyen Oracle'ın önceki sürümlerinde, daha karmaşık durumlarda genellikle hatalar vardı, bu nedenle bazen kullanırken Oracle geliştiricilerinin direnci ile karşılaşırsınız.


Oracle'ın önceki sürümlerinde bununla ilgili hatalar vardı? Ne kadar erken? Hangi sürüm (ler)?
ScottCher

Metalink'in detayları var ... her yerde açılırlar.
David Aldridge

7

Performans aynı olmalı, ancak dış birleşimler söz konusu olduğunda gelişmiş netlik nedeniyle birleştirme sürümünü kullanmanızı öneririm.

Ayrıca, birleştirme sürümü kullanılarak kasıtsız kartezyen ürünlerden kaçınılabilir.

Üçüncü bir etki, daha basit bir WHERE koşulu ile SQL'i okumak daha kolaydır.


Gerçekten anahtarın ölçütlerin belirsiz olduğu kasıtsız etkileri olduğunu düşünüyorum. Birleştirme türünü belirtirseniz, tam olarak ne elde ettiğinizi bilirsiniz. Farklı veritabanlarının ve hatta aynı veritabanı platformunun farklı sürümlerinin, boş değerleri zımni bir birleşimde farklı şekilde işleyeceğini buldum. Sol / sağ iç / dış belirttiğinizde hangisinin doğru olduğunu düşünmek için zaman harcarsınız. Belirsiz yöntemi kullandığınızda, umduğunuz / istediğiniz şekilde çalıştığını varsayarsınız.
Steve Kallestad

6

Oracle'da birleştirme anahtarı özniteliklerinin her iki tabloda da aynı şekilde adlandırılması şartıyla, bunu şu şekilde de yazabilirsiniz:

select *
from Table1 inner join Table2 using (ID);

Elbette bu aynı sorgu planına sahiptir.


Önceki revizyon cevabın anlamını değiştirdiği için baskıyı geri aldım
juan

5

Tabloların 3. normal formda olduğu bir senaryoda, tablolar arasındaki birleşmeler değişmemelidir. MÜŞTERİLERE KATILIN ve ÖDEMELER her zaman aynı kalmalıdır.

Ancak, ayırt etmelidir katılır gelen filtreler . Birleşmeler ilişkiler ve filtreler bir bütünün bölünmesi ile ilgilidir.

Standarda atıfta bulunan bazı yazarlar (örn. Jim Melton; Alan R. Simon (1993). Yeni SQL'i Anlamak: Eksiksiz Bir Kılavuz. Morgan Kaufmann. S. 11–12. ISBN 978-1-55860-245-8.) , FROM yan tümcesinde virgülle ayrılmış tablolar üzerinde JOIN sözdizimini benimsemenin yararları hakkında yazdı.

Bu bakış açısına tamamen katılıyorum.

SQL yazmanın ve aynı sonuçları elde etmenin birkaç yolu vardır, ancak ekip çalışması yapanların çoğu için kaynak kodu okunabilirliği önemli bir husustur ve tabloların birbirleriyle ilişkisini belirli filtrelerden nasıl ayırdığı kesinlikle ayırıcı bir kaynaktır. kodu.


İç birleşim, çapraz birleşim anlamına gelir. Virgül, anahtar kelime birleştirmelerinden daha düşük önceliğe sahip çapraz birleştirmedir. Açık vs "filtre" iç birleşim için önemsizdir. UF'ler sorgulama ile ilgisizdir. Standarttaki hiçbir şey, anahtar kelime birleştirmelerini virgülle tanıtamaz. Önemsiz optimizasyonlar her yerde ve benzer şekilde işlem görür. Bu cevap bir sürü yanılgıdır.
philipxy

1) Sanırım @philipxy "virgülle ayrılmış yan tümce tabloları CROSS JOINed tabloları ile aynı anlama sahiptir." Buna katılıyorum. Tabii ki, eski sözdizimine bağlı kalabilirsiniz ve bu JOIN cümleleriyle bir arada olabilir. RDBMS optimizatörleri her iki durumu da aynı şekilde mükemmel bir şekilde anlayacaktır (elbette eşdeğer olmaları durumunda) ve aynı planı hazırlayacaktır.
abrittaf

4

PostgreSQL'de kesinlikle hiçbir fark yoktur - her ikisi de aynı sorgu planına eşittir. Oracle için de durumun% 99 olduğundan eminim.


2

Her ikisi de aynı şeyi yapan iç birleşimlerdir, biri daha yeni ANSI sözdizimini kullanır.


2

İşlevsel olarak söylendiği gibi aynıdır. Katılmanın tam olarak ne yapmak istediğinizi açıklamak için daha iyi olduğunu kabul ediyorum. Pek çok kez, birleştirme yapmaya başlayana ve kafamdaki orijinalden farklı bir sorgu yapmak istediğimi fark edene kadar bir şeyi nasıl sorgulamak istediğimi bildiğimi düşündüm.


1

İşlevsel olarak, her iki sorgunun da aynı şekilde işlenmesi gerektiği doğrudur. Bununla birlikte, deneyimler, yeni birleştirme sözdizimini kullanan görünümlerden seçim yapıyorsanız, sorgularınızı da kullanarak yapılandırmanızın önemli olduğunu göstermiştir. Bir görünüm bir "birleştirme" ifadesi kullanıyorsa, ancak görünüme erişen bir sorgu "where" yan tümcesinde geleneksel birleştirme yöntemini kullanıyorsa Oracle'ın optimize edici kafası karışabilir.


Bu, görüşmelerde birleşmelerden çok bir sorun.
unexist

0

İki sorgunun kimliği belli gibi görünse de bazen garip şeyler olur. Oracle 10g (WHERE planı daha iyi olduğu için) NEREDE JOIN WHERE birleştirmek katılmak yürütürken farklı yürütme planları olan sorgu accros geldi ama basitleştirilmiş tablolar ve verilerde bu sorunu yeniden olamaz. Verilerime ve istatistiklerime bağlı olduğunu düşünüyorum. Optimizer oldukça karmaşık bir modüldür ve bazen sihirli davranır.

Bu yüzden bu soruyu genel olarak DB içlerine bağlı olduğu için cevaplayamayız. Ancak cevabın ' fark yok ' olması gerektiğini bilmeliyiz .


0

Bugün bu muamma sp bizim üretim zamanlaması birini incelerken, bir xml besleme bir 'nerede' yan tümcesi için inşa edilmiş bir tablodaki bir iç birleştirme değiştirdi .... ortalama yürütme süresi şimdi 1000 yürütme üzerinde 80 ms, oysa ortalama yürütme 2.2 saniyeden önce ... yürütme planındaki en büyük fark, anahtar aramanın ortadan kalkmasıdır ... Her iki yöntemi kullanarak test edene kadar bilmeyeceğiniz mesaj.

şerefe.



0

Kiewik'in dediği gibi, yürütme planı aynı.

JOIN deyiminin okunması sadece daha kolaydır ve ON koşulunu unutmamak ve kartezyen bir ürün elde etmek daha kolaydır. Bu hataları, birden çok türde birleşim kullanarak uzun sorgularda algılamak zor olabilir: SELECT * FROM t1, t2 WHERE t1.id = t2.some_field.

Yalnızca bir birleştirme koşulunu unutursanız, çok fazla kayıt döndüren sorguyu yürütmek için çok uzun bir süreye sahip olursunuz ... gerçekten çok fazla. Bazı insanlar sorguyu düzeltmek için bir DISTINCT kullanır, ancak yürütmek hala çok uzun.

JOIN deyimini kullanmak kesinlikle en iyi uygulamadır: daha iyi bir sürdürülebilirlik ve daha iyi okunabilirlik.

Dahası, iyi hatırlıyorsam, JOIN bellek kullanımı ile ilgili olarak optimize edilmiştir.


0

Bu iyi cevaba bir ekim var :

Sırasıyla SQL92 ve SQL89 olarak tanımlanan şey, aralarında hiçbir performans farkı yoktur, ancak INNER kelimesini atlayabilirsiniz (sadece JOIN kullanmak yeterince açıktır ve en basit sorguda 5 klavye vuruşunu kaydedersiniz, şimdi kaç tane vuruş olduğunu hayal edin olanlar).

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.