Inner join vs Where

257

Apakah ada perbedaan kinerja (dalam oracle) antara

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

Dan

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

?

juan
sumber
1
hanya untuk catatan, saya telah melihat pertanyaan mengembalikan hasil yang berbeda hanya dengan mengubah dari bergabung ke klausa mana
BlackTigerX
12
@ BlackligerX: Hasil berbeda? Apakah ada sambungan luar yang terlibat? Karena saya tidak melihat bagaimana hasil yang berbeda akan terjadi antara inner join ... onkriteria bergabung dengan menempatkan setara dalam whereklausa.
Shannon Severance
dalam versi lama dari database oracle tidak adajoin
MajidTaheri
2
@MajidTaheri: berapa usia versi Oracle yang Anda bicarakan? Setiap versi yang didukung oleh Oracle mendukung notasi JOIN.
Jonathan Leffler
Carilah jawaban umum atau praktik terbaik berdasarkan kasus-kasus sepele. Ingin melihat "pertandingan ulang" dengan klausa mana yang lebih kompleks yang melibatkan beberapa kondisi AND'd. Setidaknya dengan SQL Server ada titik silang.
crokusek

Jawaban:

195

Tidak! Rencana eksekusi yang sama, lihat dua tabel ini:

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

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

Rencana eksekusi untuk kueri menggunakan gabungan dalam:

-- 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

Dan rencana eksekusi untuk kueri menggunakan klausa WHERE.

-- 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
kiewik
sumber
4
Saya benar-benar ingin melihat apakah ada dokumentasi resmi dari Oracle yang mengatakan tentang ini
4 Leave Cover
68

Jika pengoptimal kueri melakukan tugasnya dengan benar, seharusnya tidak ada perbedaan di antara kueri tersebut. Mereka hanya dua cara untuk menentukan hasil yang diinginkan yang sama.

Craig Trader
sumber
22
Ya, kinerja harus sama. Tetapi SELECT * FROM Table1, Table2 WHERE ... sintaks is EVIL!
Joel Coehoorn
2
Saya merasa jauh lebih mudah untuk memahami UNTUK GABUNGAN INNER daripada sintaks SQL-92. Jarak tempuh Anda mungkin beragam.
Craig Trader
25
Saya menemukan sintaks WHERE lebih mudah dibaca daripada INNER JION - Saya rasa itu seperti Vegemite. Sebagian besar orang di dunia mungkin merasa menjijikkan tetapi anak-anak dibesarkan untuk memakannya, sangat menyukainya.
ScottCher
3
Vegemite memang jahat, tapi sekali lagi saya suka scrapple. Sosok pergi.
StingyJack
2
@ Darryl Saya pikir JOINs lebih mudah dibaca karena kondisi untuk bergabung dengan tabel didefinisikan di sana segera daripada "suatu tempat" dalam WHEREklausa. Saya lebih suka memesan WHEREklausa untuk membatasi dataset (misalnya WHERE DATE > (SYSDATE - 1)) daripada juga mendefinisikan bagaimana tabel terkait satu sama lain (misalnya WHERE T1.ID = T2.ID). Untuk tabel kecil seperti contoh pada pertanyaan membuat sedikit perbedaan, tetapi untuk permintaan besar yang melibatkan beberapa tabel dan beberapa kondisi, saya pikir itu membuat kueri lebih mudah dimengerti.
ImaginaryHuman072889
61

Mereka harus persis sama. Namun, sebagai praktik pengkodean, saya lebih suka melihat Bergabung. Itu jelas mengartikulasikan niat Anda,

Nescio
sumber
8
Saya setuju. Terutama jika Anda bergabung ke beberapa tabel, jauh lebih mudah untuk mem-parsing pernyataan pilih jika Anda melakukan penggabungan eksplisit.
Paul Morie
13
Memang. Bergabung mewakili hubungan semantik antara dua set data tetapi di mana menunjukkan set yang difilter. +1
EightyOne Unite
26

Menggunakan JOINmembuat kode lebih mudah dibaca, karena cukup jelas.

Tidak ada perbedaan kecepatan ( saya baru saja mengujinya ) dan rencana pelaksanaannya sama.

pengguna21241
sumber
Terima kasih. saya sedang mencari kompresi kecepatan antara dua metode ini.
Farhad Navayazdan
14

Saya tidak tahu tentang Oracle tetapi saya tahu bahwa sintaks lama sedang ditinggalkan dalam SQL Server dan akhirnya akan hilang. Sebelum saya menggunakan sintaks lama itu dalam sebuah kueri baru, saya akan memeriksa apa yang akan dilakukan Oracle.

Saya lebih suka sintaks yang lebih baru daripada pencampuran kriteria bergabung dengan kondisi tempat lain yang diperlukan. Dalam sintaks yang lebih baru, jauh lebih jelas apa yang membuat gabungan dan kondisi apa yang sedang diterapkan. Bukan masalah besar dalam kueri pendek seperti ini, tetapi akan jauh lebih membingungkan ketika Anda memiliki kueri yang lebih kompleks. Karena orang belajar pada kueri dasar, saya cenderung lebih suka orang belajar menggunakan sintaks bergabung sebelum mereka membutuhkannya dalam kueri yang kompleks.

Dan lagi saya tidak tahu Oracle secara khusus, tapi saya tahu versi SQL Server dari gaya lama bergabung kiri cacat bahkan dalam SQL Server 2000 dan memberikan hasil yang tidak konsisten (kadang-kadang bergabung kiri kadang-kadang bergabung silang), jadi seharusnya tidak pernah bekas. Semoga Oracle tidak mengalami masalah yang sama, tetapi tentu saja bergabung kiri dan kanan bisa lebih sulit untuk diekspresikan dengan benar dalam sintaks lama.

Ditambah lagi pengalaman saya (dan tentu saja ini hanya pendapat pribadi, Anda mungkin memiliki pengalaman berbeda) bahwa pengembang yang menggunakan standar ANSII bergabung cenderung memiliki pemahaman yang lebih baik tentang apa itu bergabung dan apa artinya dalam hal mendapatkan data dari database. Saya percaya bahwa karena sebagian besar orang dengan pemahaman basis data yang baik cenderung menulis pertanyaan yang lebih kompleks dan bagi saya tampaknya lebih mudah untuk mempertahankan menggunakan Standar ANSII daripada gaya lama.

HLGEM
sumber
1
Amin saudara. Turun dengan JOINERS !!
ScottCher
14

[Untuk poin bonus ...]

Menggunakan sintaks GABUNG memungkinkan Anda untuk lebih mudah mengomentari bergabung karena semuanya termasuk dalam satu baris. Ini bisa bermanfaat jika Anda men-debug permintaan yang kompleks

Seperti orang lain katakan, mereka secara fungsional sama, namun GABUNGAN lebih jelas dari pernyataan niat. Oleh karena itu dapat membantu optimizer kueri baik dalam versi oracle saat ini dalam kasus-kasus tertentu (saya tidak tahu jika ya), itu dapat membantu optimizer permintaan dalam versi Oracle masa depan (tidak ada yang punya ide), atau dapat membantu jika Anda mengubah pemasok basis data.

Chris Gill
sumber
2
Atau ... dengan mudah ubah INNER JOIN ke LEFT JOIN, jadi Anda dapat melihat gabungan mana yang menyebabkan Anda kehilangan baris yang diharapkan. Saya melakukan ini karena saya melakukan seluruh permintaan sekaligus. Jika Anda mengomentari INNER JOIN, Anda harus melakukan proses eliminasi. Itu membutuhkan waktu lebih lama. Tapi +1 untuk Anda karena ini adalah salah satu alasan favorit saya untuk INNER BERGABUNG selain dari keterbacaan!
Matthew McPeak
13

Mereka identik secara logis, tetapi dalam versi Oracle sebelumnya yang mengadopsi sintaks ANSI sering ada bug dengan itu dalam kasus yang lebih kompleks, sehingga Anda kadang-kadang akan menghadapi perlawanan dari pengembang Oracle saat menggunakannya.

David Aldridge
sumber
Versi Oracle sebelumnya memiliki bug dengan ini? Bagaimana awal? Versi apa?
ScottCher
Metalink memiliki detail ... mereka muncul di semua tempat.
David Aldridge
7

Kinerja harus identik, tetapi saya akan menyarankan menggunakan versi join karena kejelasan yang lebih baik ketika datang ke gabungan luar.

Juga produk kartesius yang tidak disengaja dapat dihindari menggunakan versi gabungan.

Efek ketiga adalah SQL yang lebih mudah dibaca dengan kondisi WHERE yang lebih sederhana.

stili
sumber
Saya benar-benar berpikir kuncinya adalah efek yang tidak disengaja di mana kriteria ambigu. Jika Anda menentukan jenis bergabung, Anda tahu persis apa yang Anda dapatkan. Saya telah menemukan bahwa basis data yang berbeda dan bahkan versi yang berbeda dari platform basis data yang sama akan menangani nilai nol secara berbeda dalam gabungan yang tersirat. Ketika Anda menentukan kiri / kanan dalam / luar Anda menghabiskan waktu untuk memikirkan mana yang benar. Ketika Anda menggunakan metode yang ambigu, Anda menganggap bahwa itu berfungsi seperti yang Anda harapkan / inginkan.
Steve Kallestad
6

Jangan lupa bahwa di Oracle, asalkan atribut kunci gabungan dinamai sama di kedua tabel, Anda juga dapat menulis ini sebagai:

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

Ini juga memiliki rencana permintaan yang sama, tentu saja.

cheduardo
sumber
Saya rollbacked edisi karena revisi sebelumnya mengubah arti jawabannya
juan
5

Dalam skenario di mana tabel berada dalam bentuk normal ke-3, gabungan antara tabel tidak boleh berubah. Yaitu bergabung dengan PELANGGAN dan PEMBAYARAN harus selalu tetap sama.

Namun, kita harus membedakan gabungan dari filter . Bergabung adalah tentang hubungan dan filter adalah tentang mempartisi keseluruhan.

Beberapa penulis, mengacu pada standar (yaitu Jim Melton; Alan R. Simon (1993). Memahami SQL Baru: Panduan Lengkap. Morgan Kaufmann. Hlm. 11-12. ISBN 978-1-55860-245-8.) , menulis tentang manfaat untuk mengadopsi sintaks GABUNG atas tabel yang dipisahkan koma dalam klausa FROM.

Saya sepenuhnya setuju dengan sudut pandang ini.

Ada beberapa cara untuk menulis SQL dan mencapai hasil yang sama tetapi bagi banyak dari mereka yang melakukan kerja tim, keterbacaan kode sumber merupakan aspek penting, dan tentu saja terpisah bagaimana tabel saling berhubungan dari filter tertentu adalah lompatan besar dalam arti memperjelas sumber kode.

abrittaf
sumber
Batin gabung di berarti gabung silang di mana. Koma adalah gabung silang dengan prioritas lebih rendah dari gabungan kata kunci. Di vs "filter" tidak relevan untuk gabung dalam. NF tidak relevan dengan permintaan. Tidak ada dalam standar yang mempromosikan kata kunci yang tergabung dalam koma. Optimalisasi sepele memperlakukan di & di tempat yang sama. Jawaban ini adalah banyak kesalahpahaman.
philipxy
1) Saya kira @philipxy sedang mencoba mengatakan "Dalam tabel klausa FROM dipisahkan oleh koma memiliki arti yang sama dengan tabel CROSS JOINed." Saya setuju dengan itu. Tentu saja, Anda dapat tetap menggunakan sintaks lama dan yang dapat berdampingan dengan klausa GABUNG. Pengoptimal RDBMS akan dengan sempurna memahami kedua kasus sebagai sama (dalam kasus mereka tentu saja setara) dan akan menguraikan rencana yang sama.
abrittaf
4

Di PostgreSQL, sama sekali tidak ada perbedaan - keduanya sama dengan rencana kueri yang sama. Saya 99% yakin itu juga berlaku untuk Oracle.

Nick Johnson
sumber
2

Keduanya sama-sama bagian dalam yang melakukan hal yang sama, satu hanya menggunakan sintaks ANSI yang lebih baru.

Bob Gettys
sumber
2

Secara fungsional mereka sama seperti yang telah dikatakan. Saya setuju bahwa melakukan join lebih baik untuk menggambarkan apa yang ingin Anda lakukan. Banyak kali saya berpikir saya tahu bagaimana saya ingin menanyakan sesuatu sampai saya mulai melakukan penggabungan dan menyadari bahwa saya ingin melakukan permintaan yang berbeda dari yang asli di kepala saya.

MattC
sumber
1

Memang benar bahwa, secara fungsional, kedua query harus diproses dengan cara yang sama. Namun, pengalaman telah menunjukkan bahwa jika Anda memilih dari tampilan yang menggunakan sintaks bergabung baru, penting untuk membuat struktur kueri Anda menggunakannya juga. Pengoptimal Oracle dapat menjadi bingung jika tampilan menggunakan pernyataan "bergabung", tetapi kueri yang mengakses tampilan menggunakan metode tradisional untuk bergabung dalam klausa "di mana".

JoshL
sumber
Itu lebih merupakan masalah dengan tampilan daripada dengan bergabung sama sekali.
ada
0

Meskipun identitas dua pertanyaan tampak jelas kadang-kadang beberapa hal aneh terjadi. Saya telah datang dengan pertanyaan yang memiliki rencana pelaksanaan yang berbeda ketika memindahkan predikat bergabung dari BERGABUNG ke WHERE di Oracle 10g (untuk rencana WHERE lebih baik), tetapi saya tidak dapat mereproduksi masalah ini dalam tabel dan data yang disederhanakan. Saya pikir itu tergantung pada data dan statistik saya. Pengoptimal adalah modul yang cukup kompleks dan terkadang berperilaku ajaib.

Itulah sebabnya kami tidak dapat menjawab pertanyaan ini secara umum karena ini tergantung pada DB internal. Tetapi kita harus tahu bahwa jawabannya harus ' tidak ada perbedaan '.

greatvovan
sumber
0

Saya mengalami teka-teki ini hari ini ketika memeriksa salah satu waktu sp kami dalam produksi, mengubah sambungan dalam pada tabel yang dibangun dari umpan xml menjadi klausa 'di mana' sebagai gantinya .... rata-rata waktu eksekutif sekarang adalah 80m lebih dari 1000 eksekusi, sedangkan sebelum rata-rata eksekutif adalah 2,2 detik ... perbedaan utama dalam rencana eksekusi adalah hilangnya pencarian kunci ... Pesan yang Anda tidak akan tahu sampai Anda diuji menggunakan kedua metode.

Bersulang.

trbullet81
sumber
0

Seperti yang dikatakan kiewik, rencana pelaksanaannya sama.

Pernyataan JOIN hanya lebih mudah dibaca, membuatnya lebih mudah untuk tidak melupakan kondisi ON dan mendapatkan produk kartesius. Kesalahan ini bisa sangat sulit dideteksi dalam kueri panjang menggunakan beberapa gabungan tipe: SELECT * FROM t1, t2 WHERE t1.id = t2.some_field.

Jika Anda lupa hanya satu syarat bergabung, Anda mendapatkan waktu yang sangat lama untuk mengeksekusi kueri yang mengembalikan terlalu banyak rekaman ... benar-benar terlalu banyak. Beberapa orang menggunakan DISTINCT untuk menambal kueri, tetapi masih sangat lama untuk dieksekusi.

Itu sebabnya, menggunakan pernyataan GABUNG tentu saja merupakan praktik terbaik: pemeliharaan yang lebih baik, dan keterbacaan yang lebih baik.

Lebih jauh lagi, jika saya ingat dengan baik, GABUNG dioptimalkan menyangkut penggunaan memori.

François ROQUEFORT
sumber
0

Saya punya tambahan untuk jawaban yang bagus itu :

Itulah yang didefinisikan sebagai SQL92 dan SQL89 masing-masing, tidak ada perbedaan kinerja di antara mereka meskipun Anda dapat menghilangkan kata INNER (menggunakan JOIN saja sudah cukup jelas dan dalam kueri paling sederhana Anda menyimpan 5 stroke keyboard sekarang bayangkan berapa banyak stroke yang ada di besar yang).

Ivanzinho
sumber