Tôi có câu hỏi dưới đây:
select databasename
from somedb.dbo.bigtable l where databasename ='someval' and source <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source)
Các truy vấn trên hoàn thành trong ba giây.
Nếu truy vấn trên trả về bất kỳ giá trị nào, chúng tôi muốn thủ tục được lưu trữ thành EXIT, vì vậy tôi viết lại như sau:
If Exists(
select databasename
from somedb.dbo.bigtable l where databasename ='someval' and source <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source)
)
Begin
Raiserror('Source missing',16,1)
Return
End
Tuy nhiên, điều này mất 10 phút.
Tôi có thể viết lại truy vấn trên như bên dưới, cũng hoàn thành trong chưa đầy 3 giây:
select databasename
from somedb.dbo.bigtable l where databasename ='someval' and source <>'kt'
and not exists(select 1 from dbo.smalltable c where c.source=l.source
if @@rowcount >0
Begin
Raiserror('Source missing',16,1)
Return
End
Vấn đề với viết lại ở trên là truy vấn trên là một phần của thủ tục được lưu trữ lớn hơn và nó trả về nhiều tập kết quả. Trong C #, chúng tôi lặp lại qua từng bộ kết quả và thực hiện một số xử lý.
Ở trên trả về một tập kết quả trống, vì vậy nếu tôi thực hiện theo phương pháp này, tôi phải thay đổi C # của mình và triển khai lại.
Vì vậy, câu hỏi của tôi là,
Tại sao sử dụng chỉ
IF EXISTS
thay đổi kế hoạch để mất rất nhiều thời gian?
Dưới đây là các chi tiết có thể giúp bạn và cho tôi biết nếu bạn cần bất kỳ chi tiết nào:
- Tạo bảng và tập lệnh thống kê để có cùng kế hoạch với tôi
- Kế hoạch thực hiện chậm
Kế hoạch thực hiện nhanh
Kế hoạch chậm sử dụng Brentozar Dán kế hoạch Kế hoạch
nhanh bằng cách sử dụng Brentozar Dán kế hoạch
Lưu ý: Cả hai truy vấn đều giống nhau (sử dụng tham số), sự khác biệt duy nhất là EXISTS
(tôi có thể đã mắc một số lỗi trong khi ẩn danh mặc dù).
Các kịch bản tạo bảng dưới đây:
http://pastebin.com/CgSHeqXc - số liệu thống kê bảng nhỏ
http://pastebin.com/GUu9KfpS - số liệu thống kê bảng lớn