Là một tham gia được tối ưu hóa cho một mệnh đề where trong thời gian chạy?


14

Khi tôi viết một truy vấn như thế này ...

select *
from table1 t1
join table2 t2
on t1.id = t2.id

Trình tối ưu hóa SQL, không chắc đó có phải là thuật ngữ chính xác không, dịch nó sang ...

select *
from table1 t1, table2 t2
where t1.id = t2.id

Về cơ bản, câu lệnh Join trong SQL Server có phải là cách dễ dàng hơn để viết sql không? Hoặc nó thực sự được sử dụng tại thời gian chạy?

Chỉnh sửa: Tôi hầu như luôn luôn, và hầu như sẽ luôn luôn sử dụng cú pháp Tham gia. Tôi chỉ tò mò những gì xảy ra.


1
Bạn có thể giải thích về "gần như"? Khi nào bạn sẽ sử dụng cú pháp kiểu cũ và tại sao?
Aaron Bertrand

2
Một trường hợp cạnh sẽ tạo ra sự khác biệt là nếu bạn thêm một (không dùng nữa) GROUP BY ALLvào
Martin Smith

@MartinSmith có ai sử dụng GROUP BY ALLvào mục đích không? :-)
Aaron Bertrand

@AaronBertrand - Tôi nghi ngờ điều đó! Đừng nghĩ rằng tôi đã từng thấy ai sử dụng nó.
Martin Smith

Câu trả lời:


20

Những người sụp đổ đến cùng một điều trong nội bộ. Trước đây là một trong những bạn nên luôn luôn viết . Quan trọng hơn, tại sao nó quan trọng? Chúng giống hệt nhau về kế hoạch thực hiện và hiệu suất (giả sử bạn không làm hỏng nó, điều này dễ thực hiện hơn với cú pháp kiểu cũ, lười biếng).

Dưới đây là bằng chứng sử dụng AdventureWorks rằng không có CROSS JOINfilterđang diễn ra.


Tham gia rõ ràng:

nhập mô tả hình ảnh ở đây


Việc tham gia ngầm:

nhập mô tả hình ảnh ở đây


Nhìn kìa Các kế hoạch giống hệt nhau, kết quả giống hệt nhau, không tham gia chéo hoặc bộ lọc được nhìn thấy ở bất cứ đâu.

(Để rõ ràng, cảnh báo về SELECTtoán tử trong cả hai trường hợp là chuyển đổi ngầm định ảnh hưởng đến tim mạch, không liên quan gì đến phép nối trong cả hai trường hợp.)


20

Nói đúng ra, có một sự khác biệt trong đầu vào của trình tối ưu hóa truy vấn giữa hai hình thức:

-- Input tree (ISO-89)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM 
    Production.Product AS p,
    Production.ProductInventory AS inv
WHERE
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

Cây đầu vào ISO-89

-- Input tree (ISO-92)
SELECT
    p.Name,
    Total = SUM(inv.Quantity)
FROM Production.Product AS p
JOIN Production.ProductInventory AS inv ON
    inv.ProductID = p.ProductID
GROUP BY
    p.Name
OPTION (RECOMPILE, QUERYTRACEON 8605, QUERYTRACEON 3604);

Cây đầu vào ISO-92

Như bạn có thể thấy, ONvị từ mệnh đề được liên kết chặt chẽ với phép nối bằng cú pháp hiện đại. Với cú pháp cũ hơn, có một phép nối chéo logic theo sau là một lựa chọn quan hệ (bộ lọc hàng).

Trình tối ưu hóa truy vấn hầu như luôn thu gọn lựa chọn quan hệ vào liên kết trong quá trình tối ưu hóa, có nghĩa là hai biểu mẫu sẽ rất có thể tạo ra các gói truy vấn tương đương, nhưng không có đảm bảo thực tế.


4

Đối với kết nối bên trong, chúng có thể hoán đổi cho nhau, nhưng đối với Tham gia ngoài chúng có ý nghĩa khác nhau - BẬT phù hợp và WHERE là lọc đơn giản. Vì vậy, tốt hơn hết là bạn nên tuân thủ đúng cú pháp THAM GIA trên ON.


4

OK, tôi đã tò mò vì vậy tôi đã làm một bài kiểm tra. Tôi đã có kế hoạch thực hiện thực tế cho sau đây.

select * 
from sys.database_principals prin, sys.database_permissions perm
WHERE prin.principal_id = perm.grantee_principal_id

select * 
from sys.database_principals prin
JOIN sys.database_permissions perm
    ON prin.principal_id = perm.grantee_principal_id

Tôi so sánh chúng theo đối tượng và chúng giống hệt nhau. Vì vậy, ít nhất là đối với một ví dụ rất đơn giản, họ đã đưa ra điều tương tự. Tôi cũng đã kiểm tra số liệu thống kê IO và thời gian và chúng đủ gần để trở thành điều tương tự.

Điều đó đang được nói, bạn nên sử dụng JOINcú pháp bởi vì nó dễ đọc hơn và bạn ít có khả năng mắc lỗi, đặc biệt là trong các truy vấn phức tạp. Và cú pháp *=/ =*cho các phép OUTERnối đã bị xóa kể từ SQL-Server 2005.

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.