Tôi có một lớp các truy vấn kiểm tra sự tồn tại của một trong hai điều. Nó là của hình thức
SELECT CASE
WHEN EXISTS (SELECT 1 FROM ...)
OR EXISTS (SELECT 1 FROM ...)
THEN 1 ELSE 0 END;
Câu lệnh thực tế được tạo bằng C và được thực hiện dưới dạng truy vấn đặc biệt qua kết nối ODBC.
Gần đây, người ta đã phát hiện ra rằng CHỌN thứ hai có thể sẽ nhanh hơn CHỌN thứ nhất trong hầu hết các trường hợp và việc chuyển đổi thứ tự của hai mệnh đề EXISTS đã gây ra sự tăng tốc mạnh mẽ trong ít nhất một trường hợp thử nghiệm lạm dụng mà chúng tôi vừa tạo.
Điều rõ ràng cần làm là chỉ cần tiếp tục và chuyển đổi hai mệnh đề, nhưng tôi muốn xem liệu ai đó quen thuộc hơn với SQL Server có quan tâm đến việc này không. Cảm giác như tôi đang dựa vào sự trùng hợp và một "chi tiết thực hiện".
(Cũng có vẻ như nếu SQL Server thông minh hơn, nó sẽ thực thi song song cả hai mệnh đề EXISTS và cho phép bất kỳ cái nào hoàn thành ngắn mạch đầu tiên.
Có cách nào tốt hơn để SQL Server luôn cải thiện thời gian chạy của một truy vấn như vậy không?
Cập nhật
Cảm ơn bạn đã dành thời gian và quan tâm đến câu hỏi của tôi. Tôi không mong đợi câu hỏi về kế hoạch truy vấn thực tế, nhưng tôi sẵn sàng chia sẻ chúng.
Đây là một thành phần phần mềm hỗ trợ SQL Server 2008R2 trở lên. Hình dạng của dữ liệu có thể khá khác nhau tùy thuộc vào cấu hình và cách sử dụng. Đồng nghiệp của tôi đã nghĩ đến việc thực hiện thay đổi này cho truy vấn vì bảng (trong ví dụ) dbf_1162761$z$rv$1257927703
sẽ luôn có số lượng lớn hơn hoặc bằng số hàng trong dbf_1162761$z$dd$1257927703
bảng so với bảng - đôi khi nhiều hơn đáng kể (thứ tự cường độ).
Dưới đây là trường hợp lạm dụng tôi đã đề cập. Truy vấn đầu tiên là truy vấn chậm và mất khoảng 20 giây. Truy vấn thứ hai hoàn thành ngay lập tức.
Để biết giá trị của nó, bit "TỐI ƯU HÓA CHO UNKNOWN" cũng đã được thêm vào gần đây vì việc đánh hơi tham số đã làm hỏng một số trường hợp nhất định.
Truy vấn gốc:
SELECT CASE
WHEN EXISTS (SELECT 1 FROM zumero.dbf_1162761$z$rv$1257927703 rv INNER JOIN zumero.dbf_1162761$t$tx tx ON tx.txid=rv.txid WHERE tx.generation BETWEEN 1500 AND 2502)
OR EXISTS (SELECT 1 FROM zumero.dbf_1162761$z$dd$1257927703 dd INNER JOIN zumero.dbf_1162761$t$tx tx ON tx.txid=dd.txid WHERE tx.generation BETWEEN 1500 AND 2502)
THEN 1 ELSE 0 END
OPTION (OPTIMIZE FOR UNKNOWN)
Kế hoạch ban đầu:
|--Compute Scalar(DEFINE:([Expr1006]=CASE WHEN [Expr1007] THEN (1) ELSE (0) END))
|--Nested Loops(Left Semi Join, DEFINE:([Expr1007] = [PROBE VALUE]))
|--Constant Scan
|--Concatenation
|--Nested Loops(Inner Join, WHERE:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[txid] as [rv].[txid]=[scale].[zumero].[dbf_1162761$t$tx].[txid] as [tx].[txid]))
| |--Clustered Index Scan(OBJECT:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[PK__dbf_1162__97770A2F62EEAE79] AS [rv]), WHERE:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[txid] as [rv].[txid]>(0)))
| |--Index Seek(OBJECT:([scale].[zumero].[dbf_1162761$t$tx].[gendex] AS [tx]), SEEK:([tx].[generation] >= (1500) AND [tx].[generation] <= (2502)) ORDERED FORWARD)
|--Nested Loops(Inner Join, OUTER REFERENCES:([tx].[txid]))
|--Clustered Index Scan(OBJECT:([scale].[zumero].[dbf_1162761$t$tx].[PK__dbf_1162__E3BA953EC2197789] AS [tx]), WHERE:([scale].[zumero].[dbf_1162761$t$tx].[generation] as [tx].[generation]>=(1500) AND [scale].[zumero].[dbf_1162761$t$tx].[generation] as [tx].[generation]<=(2502)) ORDERED FORWARD)
|--Index Seek(OBJECT:([scale].[zumero].[dbf_1162761$z$dd$1257927703].[n$dbf_1162761$z$dd$txid$1257927703] AS [dd]), SEEK:([dd].[txid]=[scale].[zumero].[dbf_1162761$t$tx].[txid] as [tx].[txid]), WHERE:([scale].[zumero].[dbf_1162761$z$dd$1257927703].[txid] as [dd].[txid]>(0)) ORDERED FORWARD)
Đã sửa lỗi truy vấn:
SELECT CASE
WHEN EXISTS (SELECT 1 FROM zumero.dbf_1162761$z$dd$1257927703 dd INNER JOIN zumero.dbf_1162761$t$tx tx ON tx.txid=dd.txid WHERE tx.generation BETWEEN 1500 AND 2502)
OR EXISTS (SELECT 1 FROM zumero.dbf_1162761$z$rv$1257927703 rv INNER JOIN zumero.dbf_1162761$t$tx tx ON tx.txid=rv.txid WHERE tx.generation BETWEEN 1500 AND 2502)
THEN 1 ELSE 0 END
OPTION (OPTIMIZE FOR UNKNOWN)
Gói cố định:
|--Compute Scalar(DEFINE:([Expr1006]=CASE WHEN [Expr1007] THEN (1) ELSE (0) END))
|--Nested Loops(Left Semi Join, DEFINE:([Expr1007] = [PROBE VALUE]))
|--Constant Scan
|--Concatenation
|--Nested Loops(Inner Join, OUTER REFERENCES:([tx].[txid]))
| |--Clustered Index Scan(OBJECT:([scale].[zumero].[dbf_1162761$t$tx].[PK__dbf_1162__E3BA953EC2197789] AS [tx]), WHERE:([scale].[zumero].[dbf_1162761$t$tx].[generation] as [tx].[generation]>=(1500) AND [scale].[zumero].[dbf_1162761$t$tx].[generation] as [tx].[generation]<=(2502)) ORDERED FORWARD)
| |--Index Seek(OBJECT:([scale].[zumero].[dbf_1162761$z$dd$1257927703].[n$dbf_1162761$z$dd$txid$1257927703] AS [dd]), SEEK:([dd].[txid]=[scale].[zumero].[dbf_1162761$t$tx].[txid] as [tx].[txid]), WHERE:([scale].[zumero].[dbf_1162761$z$dd$1257927703].[txid] as [dd].[txid]>(0)) ORDERED FORWARD)
|--Nested Loops(Inner Join, WHERE:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[txid] as [rv].[txid]=[scale].[zumero].[dbf_1162761$t$tx].[txid] as [tx].[txid]))
|--Clustered Index Scan(OBJECT:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[PK__dbf_1162__97770A2F62EEAE79] AS [rv]), WHERE:([scale].[zumero].[dbf_1162761$z$rv$1257927703].[txid] as [rv].[txid]>(0)))
|--Index Seek(OBJECT:([scale].[zumero].[dbf_1162761$t$tx].[gendex] AS [tx]), SEEK:([tx].[generation] >= (1500) AND [tx].[generation] <= (2502)) ORDERED FORWARD)