Tham gia nội bộ vs ở đâu


257

Có sự khác biệt về hiệu suất (trong lời tiên tri) giữa

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

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

?


1
chỉ để ghi lại, tôi đã thấy các truy vấn chỉ trả về các kết quả khác nhau bằng cách thay đổi từ tham gia sang mệnh đề
where

12
@BlackTigerX: Kết quả khác nhau? Có bất kỳ tham gia bên ngoài liên quan? Bởi vì tôi không thấy các kết quả khác nhau sẽ xảy ra như thế nào giữa một inner join ... ontiêu chí tham gia tương đương trong wheređiều khoản.
Shannon Severance

trong phiên bản cũ của cơ sở dữ liệu oracle không tồn tạijoin
MajidTaheri

2
@MajidTaheri: bạn đang nói về phiên bản Oracle bao nhiêu tuổi? Bất kỳ phiên bản nào được Oracle hỗ trợ đều hỗ trợ ký hiệu THAM GIA.
Jonathan Leffler

Xem ra cho câu trả lời chung hoặc thực hành tốt nhất dựa trên các trường hợp tầm thường. Muốn xem "kết hợp lại" với các mệnh đề phức tạp hơn trong đó có nhiều điều kiện liên quan đến nhiều điều kiện AND. Ít nhất với SQL Server có một điểm giao nhau.
crokusek

Câu trả lời:


195

Không! Cùng một kế hoạch thực hiện, hãy nhìn vào hai bảng sau:

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

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

Kế hoạch thực hiện cho truy vấn bằng cách sử dụng phép nối bên trong:

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

Và kế hoạch thực hiện cho truy vấn bằng cách sử dụng mệnh đề 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

4
Tôi thực sự muốn xem liệu có tài liệu chính thức nào từ Oracle nói về điều này không
4 Để lại trang bìa

68

Nếu trình tối ưu hóa truy vấn đang thực hiện đúng công việc của nó, sẽ không có sự khác biệt giữa các truy vấn đó. Chúng chỉ là hai cách để xác định cùng một kết quả mong muốn.


22
Vâng, hiệu suất nên giống nhau. Nhưng cú pháp CHỌN * TỪ Bảng1, Bảng2 Ở ĐÂU ... là EVIL!
Joel Coehoorn

2
Tôi thấy việc hiểu FOR INNER THAM GIA dễ dàng hơn nhiều so với cú pháp SQL-92. Số dặm của bạn có thể thay đổi.
Craig Trader

25
Tôi thấy cú pháp WHERE dễ đọc hơn INNER JION - Tôi đoán nó giống như Vegemite. Hầu hết mọi người trên thế giới có thể thấy nó kinh tởm nhưng những đứa trẻ đã ăn nó rất thích nó.
ScottCher

3
Vegemite là khó chịu thực sự, nhưng sau đó một lần nữa tôi yêu scrapple. Đi hình.
Cá đuối gai độc

2
@Darryl Tôi nghĩ rằng JOINs dễ đọc hơn vì điều kiện để tham gia các bảng được xác định ngay tại đó thay vì "ở đâu đó" trong WHEREmệnh đề. Tôi thích bảo lưu WHEREmệnh đề cho việc giới hạn tập dữ liệu (ví dụ WHERE DATE > (SYSDATE - 1)) thay vì cũng xác định cách các bảng liên quan với nhau (ví dụ WHERE T1.ID = T2.ID). Đối với một bảng nhỏ như ví dụ trong câu hỏi tạo ra sự khác biệt nhỏ, nhưng đối với các truy vấn lớn liên quan đến một số bảng và một số điều kiện, tôi nghĩ rằng nó làm cho truy vấn dễ hiểu hơn nhiều.
ImaginaryHuman072889

61

Chúng nên giống hệt nhau. Tuy nhiên, là một thực hành mã hóa, tôi muốn xem Tham gia. Nó nói rõ ý định của bạn,


8
Tôi đồng ý. Đặc biệt nếu bạn đang tham gia vào nhiều bảng, việc phân tích một câu lệnh chọn sẽ dễ dàng hơn rất nhiều nếu bạn thực hiện các phép nối rõ ràng.
Paul Morie

13
Thật. Tham gia thể hiện mối quan hệ ngữ nghĩa giữa hai bộ dữ liệu nhưng một nơi gợi ý một bộ lọc. +1
EightyOne Đoàn kết

26

Việc sử dụng JOINlàm cho mã dễ đọc hơn, vì nó tự giải thích.

Không có sự khác biệt về tốc độ ( tôi vừa thử nó ) và kế hoạch thực hiện là như nhau.


Cảm ơn bạn. tôi đã tìm kiếm nén tốc độ giữa hai phương pháp này.
Farhad Navayazdan

14

Tôi không biết về Oracle nhưng tôi biết rằng cú pháp cũ đang bị phản đối trong SQL Server và cuối cùng sẽ biến mất. Trước khi tôi sử dụng cú pháp cũ đó trong một truy vấn mới, tôi sẽ kiểm tra xem Oracle dự định làm gì với nó.

Tôi thích cú pháp mới hơn là pha trộn các tiêu chí nối với các điều kiện cần thiết khác. Trong cú pháp mới hơn, rõ ràng hơn những gì tạo ra phép nối và những điều kiện khác đang được áp dụng. Không thực sự là một vấn đề lớn trong một truy vấn ngắn như thế này, nhưng nó trở nên khó hiểu hơn nhiều khi bạn có một truy vấn phức tạp hơn. Vì mọi người học về các truy vấn cơ bản, tôi sẽ có xu hướng thích mọi người học cách sử dụng cú pháp nối trước khi họ cần nó trong một truy vấn phức tạp.

Và một lần nữa tôi không biết cụ thể về Oracle, nhưng tôi biết phiên bản SQL Server của kiểu nối cũ bị lỗi ngay cả trong SQL Server 2000 và cho kết quả không nhất quán (đôi khi là nối trái đôi khi là nối chéo), vì vậy nó không bao giờ nên đã sử dụng. Hy vọng rằng Oracle không gặp phải vấn đề tương tự, nhưng chắc chắn các phép nối trái và phải có thể khó hơn để diễn đạt đúng theo cú pháp cũ.

Thêm vào đó là kinh nghiệm của tôi (và tất nhiên đây hoàn toàn là ý kiến ​​cá nhân, bạn có thể có kinh nghiệm khác biệt) rằng các nhà phát triển sử dụng tham gia tiêu chuẩn ANSII có xu hướng hiểu rõ hơn về việc tham gia là gì và ý nghĩa của việc tham gia dữ liệu ra khỏi cơ sở dữ liệu. Tôi tin rằng hầu hết những người có hiểu biết về cơ sở dữ liệu tốt thường có xu hướng viết các truy vấn phức tạp hơn và những điều đó dường như dễ dàng hơn nhiều để duy trì sử dụng Tiêu chuẩn ANSII so với kiểu cũ.


1
Amen anh. Đả đảo các THAM GIA !!
ScottCher

14

[Để có điểm thưởng ...]

Sử dụng cú pháp THAM GIA cho phép bạn dễ dàng nhận xét tham gia hơn vì tất cả được bao gồm trên một dòng. Điều này thể hữu ích nếu bạn đang gỡ lỗi một truy vấn phức tạp

Như mọi người khác nói, chúng có chức năng giống nhau, tuy nhiên THAM GIA rõ ràng hơn về tuyên bố về ý định. Do đó, nó có thể giúp trình tối ưu hóa truy vấn trong các phiên bản tiên tri hiện tại trong một số trường hợp nhất định (tôi không biết nếu có), nó có thể giúp trình tối ưu hóa truy vấn trong các phiên bản tương lai của Oracle (không ai có ý tưởng nào) hoặc có thể giúp nếu bạn thay đổi nhà cung cấp cơ sở dữ liệu.


2
Hoặc ... dễ dàng thay đổi THAM GIA VÀO THAM GIA TRÁI PHIẾU, để bạn biết được tham gia nào đang khiến bạn bỏ lỡ các hàng dự kiến. Tôi làm điều này bởi vì tôi làm toàn bộ truy vấn cùng một lúc. Nếu bạn nhận xét ra THAM GIA, bạn phải thực hiện một quá trình loại bỏ. Phải mất nhiều thời gian hơn. Nhưng +1 cho bạn vì đây là một trong những lý do yêu thích của tôi để INNER THAM GIA ngoài khả năng đọc!
Matthew McPeak

13

Chúng giống hệt nhau về mặt logic, nhưng trong các phiên bản trước đó của Oracle đã áp dụng cú pháp ANSI, thường có lỗi với nó trong các trường hợp phức tạp hơn, do đó đôi khi bạn sẽ gặp phải sự kháng cự từ các nhà phát triển Oracle khi sử dụng nó.


Các phiên bản trước của Oracle có lỗi với điều này? Làm thế nào sớm? Phiên bản nào?
ScottCher

Metalink có chi tiết ... họ bật lên khắp nơi.
David Aldridge

7

Hiệu suất phải giống hệt nhau, nhưng tôi khuyên bạn nên sử dụng phiên bản tham gia do sự rõ ràng được cải thiện khi nói đến các kết nối bên ngoài.

Ngoài ra các sản phẩm cartesian không chủ ý có thể tránh được bằng cách sử dụng phiên bản tham gia.

Hiệu ứng thứ ba là một SQL dễ đọc hơn với điều kiện WHERE đơn giản hơn.


Tôi thực sự nghĩ rằng chìa khóa là hiệu ứng không chủ ý trong đó các tiêu chí là mơ hồ. Nếu bạn chỉ định loại tham gia, bạn biết chính xác những gì bạn đang nhận được. Tôi đã thấy rằng các cơ sở dữ liệu khác nhau và thậm chí các phiên bản khác nhau của cùng một nền tảng cơ sở dữ liệu sẽ xử lý các giá trị null khác nhau trong một phép nối ngụ ý. Khi bạn chỉ định bên trái / bên trong / bên ngoài, bạn dành thời gian để suy nghĩ xem điều gì là đúng. Khi bạn sử dụng phương thức mơ hồ, bạn cho rằng nó hoạt động theo cách bạn hy vọng / dự định.
Steve Kallestad

6

Đừng quên rằng trong Oracle, với điều kiện các thuộc tính khóa tham gia được đặt tên giống nhau trong cả hai bảng, bạn cũng có thể viết điều này như sau:

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

Điều này cũng có kế hoạch truy vấn tương tự, tất nhiên.


Tôi đã quay lại phiên bản vì bản sửa đổi trước đó đã thay đổi ý nghĩa của câu trả lời
juan

5

Trong trường hợp các bảng ở dạng bình thường thứ 3, các phép nối giữa các bảng không nên thay đổi. Tức là tham gia KHÁCH HÀNG và THANH TOÁN nên luôn giữ nguyên.

Tuy nhiên, chúng ta nên phân biệt các phép nối với các bộ lọc . Tham gia là về mối quan hệ và bộ lọc là về phân vùng tổng thể.

Một số tác giả, đề cập đến tiêu chuẩn (ví dụ Jim Melton; Alan R. Simon (1993). Tìm hiểu về SQL mới: Hướng dẫn đầy đủ. Morgan Kaufmann. Trang 11 111212. , đã viết về các lợi ích để áp dụng cú pháp THAM GIA trên các bảng được phân tách bằng dấu phẩy trong mệnh đề TỪ.

Tôi hoàn toàn đồng ý với quan điểm này.

Có một số cách để viết SQL và đạt được kết quả tương tự, nhưng đối với nhiều người làm việc theo nhóm, mức độ dễ đọc của mã nguồn là một khía cạnh quan trọng và chắc chắn tách biệt các bảng liên quan với nhau từ các bộ lọc cụ thể là một bước nhảy vọt lớn trong ý nghĩa làm rõ nguồn mã.


Tham gia bên trong có nghĩa là tham gia chéo ở đâu. Dấu phẩy là tham gia chéo với mức độ ưu tiên thấp hơn so với tham gia từ khóa. Bật vs "bộ lọc" không liên quan để tham gia bên trong. Các NF không liên quan đến truy vấn. Không có gì trong tiêu chuẩn thúc đẩy từ khóa tham gia qua dấu phẩy. Tối ưu hóa tầm thường đối xử trên & nơi giống nhau. Câu trả lời này là một loạt các quan niệm sai lầm.
philipxy

1) Tôi đoán @philipxy đang cố gắng nói "Trong các mệnh đề TỪ được phân tách bằng dấu phẩy có cùng ý nghĩa với các bảng CROSS THAM GIA." Tôi đồng ý với điều đó. Tất nhiên, bạn có thể dính vào cú pháp cũ và điều đó có thể cùng tồn tại với các mệnh đề THAM GIA. Các trình tối ưu hóa RDBMS sẽ hiểu hoàn hảo cả hai trường hợp là như nhau (trong trường hợp chúng tương đương với khóa học) và sẽ xây dựng cùng một kế hoạch.
abrittaf

4

Trong PostgreSQL, chắc chắn không có sự khác biệt - cả hai đều tương đương với cùng một kế hoạch truy vấn. Tôi chắc chắn 99% đó cũng là trường hợp của Oracle.


2

Cả hai đều tham gia bên trong làm cùng một việc, một cách đơn giản là sử dụng cú pháp ANSI mới hơn.


2

Về mặt chức năng, chúng giống như đã được nói. Tôi đồng ý mặc dù việc tham gia là tốt hơn để mô tả chính xác những gì bạn muốn làm. Rất nhiều lần tôi đã nghĩ rằng tôi biết tôi muốn truy vấn điều gì cho đến khi tôi bắt đầu thực hiện các phép nối và nhận ra tôi muốn thực hiện một truy vấn khác với truy vấn ban đầu trong đầu.


1

Đúng là về mặt chức năng, cả hai truy vấn nên được xử lý theo cùng một cách. Tuy nhiên, kinh nghiệm đã chỉ ra rằng nếu bạn đang chọn từ các chế độ xem sử dụng cú pháp nối mới, điều quan trọng là phải cấu trúc các truy vấn của bạn bằng cách sử dụng nó. Trình tối ưu hóa của Oracle có thể bị lẫn lộn nếu một khung nhìn sử dụng câu lệnh "tham gia", nhưng một truy vấn truy cập vào khung nhìn sử dụng phương thức nối truyền thống trong mệnh đề "where".


Đó là một vấn đề với lượt xem nhiều hơn là tham gia.
unexist

0

Mặc dù danh tính của hai truy vấn có vẻ rõ ràng đôi khi một số điều kỳ lạ xảy ra. Tôi đã đến các truy vấn có các kế hoạch thực hiện khác nhau khi di chuyển vị từ tham gia từ THAM GIA sang WHERE trong Oracle 10g (đối với kế hoạch WHERE là tốt hơn), nhưng tôi không thể tái tạo vấn đề này trong các bảng và dữ liệu đơn giản. Tôi nghĩ rằng nó phụ thuộc vào dữ liệu và số liệu thống kê của tôi. Trình tối ưu hóa là mô-đun khá phức tạp và đôi khi nó hoạt động một cách kỳ diệu.

Đó là lý do tại sao chúng ta không thể trả lời cho câu hỏi này nói chung vì nó phụ thuộc vào nội bộ DB. Nhưng chúng ta nên biết rằng câu trả lời phải là ' không có sự khác biệt '.


0

tôi đã có câu hỏi hóc búa này hôm nay khi kiểm tra một trong những thời gian sản xuất của chúng tôi, đã thay đổi một phép nối bên trong trên một bảng được xây dựng từ nguồn cấp dữ liệu xml thành mệnh đề 'trong đó' thay vào đó .... thời gian thực hiện trung bình hiện là 80ms trên 1000 lần thực thi trước khi thực hiện trung bình là 2,2 giây ... sự khác biệt lớn trong kế hoạch thực hiện là sự không đồng ý của một tra cứu chính ... Thông điệp mà bạn không biết cho đến khi bạn đã thử nghiệm bằng cả hai phương pháp.

chúc mừng



0

Như kiewik đã nói, kế hoạch thực hiện là như nhau.

Câu lệnh THAM GIA chỉ dễ đọc hơn, giúp dễ dàng không quên điều kiện BẬT và nhận sản phẩm cartesian. Các lỗi này có thể khá khó phát hiện trong các truy vấn dài bằng cách sử dụng nhiều phép nối loại: CHỌN * TỪ t1, t2 WHERE t1.id = t2.some_field.

Nếu bạn quên chỉ một điều kiện tham gia, bạn sẽ mất rất nhiều thời gian để thực hiện truy vấn trả về quá nhiều bản ghi ... thực sự quá nhiều. Một số poeple sử dụng DISTINCT để vá truy vấn, nhưng vẫn còn rất lâu để thực thi.

Đó chính xác là lý do tại sao, sử dụng câu lệnh THAM GIA chắc chắn là cách thực hành tốt nhất: khả năng bảo trì tốt hơn và khả năng đọc tốt hơn.

Hơn nữa, nếu tôi nhớ rõ, THAM GIA được tối ưu hóa liên quan đến việc sử dụng bộ nhớ.


0

Tôi có một bổ sung cho câu trả lời hay đó :

Đó là những gì được định nghĩa tương ứng là SQL92 và SQL89, không có sự khác biệt về hiệu năng giữa chúng mặc dù bạn có thể bỏ qua từ INNER (chỉ cần sử dụng THAM GIA là đủ rõ ràng và trong truy vấn đơn giản nhất bạn lưu 5 nét bàn phím bây giờ hãy tưởng tượng có bao nhiêu nét trong bàn phím những cái).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.