2009-11-02 23 views
33

Tôi vừa mới biết về sự tồn tại của mệnh đề "EXCEPT" mới trong SQL Server (một chút trễ, tôi biết ...) thông qua mã đọc được viết bởi một đồng nghiệp. Nó thực sự làm tôi ngạc nhiên!Khi nào sử dụng EXCEPT như trái ngược với KHÔNG tồn tại trong SQL giao dịch?

Nhưng sau đó tôi có một số câu hỏi liên quan đến việc sử dụng của nó: khi nào được khuyến nghị sử dụng? Có một sự khác biệt, hiệu suất khôn ngoan, giữa việc sử dụng nó so với một truy vấn tương quan sử dụng "AND NOT EXISTS ..."?

Sau khi đọc bài viết của EXCEPT trong BOL tôi nghĩ nó chỉ là một cách viết tắt cho tùy chọn thứ hai, nhưng tôi đã rất ngạc nhiên khi tôi viết lại một vài truy vấn bằng cách sử dụng nó (để họ có cú pháp "AND NOT EXISTS" quen thuộc hơn với tôi) và sau đó kiểm tra kế hoạch thực hiện - bất ngờ! Phiên bản EXCEPT có kế hoạch thực thi ngắn hơn và cũng được thực hiện nhanh hơn. Điều này luôn luôn như vậy?

Vì vậy, tôi muốn biết: các nguyên tắc sử dụng công cụ mạnh mẽ này là gì?

+0

Tốt tham khảo: http://explainextended.com/2009/09/15/not-in-vs-not-exists-vs -left-join-is-null-sql-server/ –

+0

@rexem: Tham chiếu của bạn không bao giờ đề cập đến mệnh đề EXCEPT ... –

+0

Không, nhưng nó không nói về NOT EXISTS hiệu suất. Trang web cũng là một tài liệu tham khảo tuyệt vời cho các câu hỏi liên quan về hiệu suất của db. –

Trả lời

2

Không có kế hoạch thực hiện kế hoạch của máy chủ SQL. Tôi đã luôn luôn tìm thấy khi có vấn đề hiệu suất mà nó hoàn toàn tùy ý (từ góc nhìn của người dùng, tôi chắc chắn rằng các nhà văn thuật toán sẽ hiểu tại sao) khi một cú pháp thực hiện một kế hoạch thực hiện tốt hơn là một cú pháp khác.

Trong trường hợp này, một cái gì đó về so sánh tham số truy vấn cho phép SQL tìm ra một lối tắt mà nó không thể từ một câu lệnh chọn thẳng. Tôi chắc chắn đó là sự thiếu hụt trong thuật toán. Nói cách khác, bạn có thể nội suy hợp lý cùng một điều, nhưng thuật toán không làm cho bản dịch đó trên một truy vấn tồn tại. Đôi khi đó là bởi vì một thuật toán có thể tin tưởng rằng nó sẽ mất nhiều thời gian hơn để thực thi hơn chính truy vấn đó, hoặc ít nhất là các nhà thiết kế thuật toán nghĩ như vậy.

33

EXCEPT xử lý các giá trị NULL là phù hợp.

truy vấn này:

WITH q (value) AS 
     (
     SELECT NULL 
     UNION ALL 
     SELECT 1 
     ), 
     p (value) AS 
     (
     SELECT NULL 
     UNION ALL 
     SELECT 2 
     ) 
SELECT * 
FROM q 
WHERE value NOT IN 
     (
     SELECT value 
     FROM p 
     ) 

sẽ trả về một rowset trống.

truy vấn này:

WITH q (value) AS 
     (
     SELECT NULL 
     UNION ALL 
     SELECT 1 
     ), 
     p (value) AS 
     (
     SELECT NULL 
     UNION ALL 
     SELECT 2 
     ) 
SELECT * 
FROM q 
WHERE NOT EXISTS 
     (
     SELECT NULL 
     FROM p 
     WHERE p.value = q.value 
     ) 

sẽ trở lại

NULL 
1 

, và điều này:

WITH q (value) AS 
     (
     SELECT NULL 
     UNION ALL 
     SELECT 1 
     ), 
     p (value) AS 
     (
     SELECT NULL 
     UNION ALL 
     SELECT 2 
     ) 
SELECT * 
FROM q 
EXCEPT 
SELECT * 
FROM p 

sẽ trở lại:

1 

tham khảo đệ quy cũng được cho phép trong EXCEPT điều khoản trong một đệ quy CTE, mặc dù nó cư xử theo một cách kỳ lạ: nó sẽ trả về tất cả mọi thứ trừ hàng cuối cùng của một tập trước, không phải tất cả mọi thứ ngoại trừ toàn bộ theo thời gian:

WITH q (value) AS 
     (
     SELECT 1 
     UNION ALL 
     SELECT 2 
     UNION ALL 
     SELECT 3 
     ), 
     rec (value) AS 
     (
     SELECT value 
     FROM q 
     UNION ALL 
     SELECT * 
     FROM (
       SELECT value 
       FROM q 
       EXCEPT 
       SELECT value 
       FROM rec 
       ) q2 
     ) 
SELECT TOP 10 * 
FROM rec 

--- 
1 
2 
3 
-- original set 
1 
2 
-- everything except the last row of the previous set, that is 3 
1 
3 
-- everything except the last row of the previous set, that is 2 
1 
2 
-- everything except the last row of the previous set, that is 3, etc. 
1 

SQL Server nhà phát triển chắc hẳn đã quên cấm điều đó.

+0

Ngoài ra 'except' trả về một Set, do đó các giá trị khác biệt. – Magnus

2

EXCEPT so sánh tất cả các cột (được ghép nối) của hai lựa chọn đầy đủ. NOT EXISTS so sánh hai hoặc nhiều bảng được mã hóa với các điều kiện được chỉ định trong mệnh đề WHERE trong truy vấn phụ sau từ khóa NOT EXISTS.

EXCEPT có thể được viết lại bằng cách sử dụng NOT EXISTS. (TRỪ ALL có thể được viết lại bằng cách sử dụng ROW_NUMBER và không tồn tại.)

Got này từ here

8

Tôi đã làm rất nhiều phân tích trừ, không tồn tại, không phải trong và để lại bên ngoài tham gia. Nói chung, phép nối ngoài bên trái là nhanh nhất cho việc tìm kiếm các hàng bị thiếu, đặc biệt là việc nối trên một khóa chính. Không phải trong có thể rất nhanh nếu bạn biết nó sẽ là một danh sách nhỏ trở lại trong lựa chọn.

tôi sử dụng TRỪ rất nhiều để so sánh những gì đang được trả lại khi viết lại mã. Chạy kết quả lưu mã cũ. Chạy các kết quả tiết kiệm mã mới và sau đó sử dụng ngoại trừ để nắm bắt tất cả các khác biệt. Đó là một cách rất nhanh chóng và dễ dàng để tìm sự khác biệt, đặc biệt là khi cần để có được tất cả sự khác biệt bao gồm cả null. Rất tốt cho trên bay dễ dàng mã hóa.

Nhưng, mọi tình huống đều khác nhau. Tôi nói với mọi nhà phát triển mà tôi từng cố vấn. Thử nó. Làm timings tất cả các cách khác nhau. Hãy thử nó, thời gian nó, làm điều đó.

2

Nếu truy vấn của bạn được tinh chỉnh thì không có sự khác biệt hiệu suất b/w sử dụng mệnh đề EXCEPT và NOT EXIST/NOT IN .. lần đầu tiên khi tôi chạy EXCEPT sau khi thay đổi truy vấn tương quan thành nó .. Tôi ngạc nhiên vì nó trở lại với kết quả chỉ trong 7 giây trong khi truy vấn tương quan đã trở lại trong 22 giây .. sau đó tôi đã sử dụng mệnh đề riêng biệt trong truy vấn tương quan và reran của mình .. nó cũng trở lại sau 7 giây. hoặc không có thời gian để tinh chỉnh truy vấn của bạn nếu không cả hai đều cùng hiệu suất khôn ngoan ..

Các vấn đề liên quan