Tôi có một câu lệnh CẬP NHẬT SQL với mệnh đề "TOP (X)" và hàng tôi đang cập nhật các giá trị trong có khoảng 4 tỷ hàng. Khi tôi sử dụng "TOP (10)", tôi nhận được một kế hoạch thực hiện gần như ngay lập tức, nhưng khi tôi sử dụng "TOP (50)" hoặc lớn hơn, truy vấn không bao giờ (ít nhất là trong khi tôi đang chờ) kết thúc và nó sử dụng một kế hoạch thực hiện hoàn toàn khác. Truy vấn nhỏ hơn sử dụng một kế hoạch rất đơn giản với một cặp tìm kiếm chỉ mục và nối vòng lặp lồng nhau, trong đó cùng một truy vấn (với một số hàng khác nhau trong mệnh đề TOP của câu lệnh UPDATE) sử dụng một kế hoạch bao gồm hai tìm kiếm chỉ mục khác nhau , một bộ đệm bảng, song song và một loạt các phức tạp khác.
Tôi đã sử dụng "TÙY CHỌN (SỬ DỤNG KẾ HOẠCH ...)" để buộc nó sử dụng kế hoạch thực hiện được tạo bởi truy vấn nhỏ hơn - khi tôi thực hiện việc này, tôi có thể cập nhật lên tới 100.000 hàng trong vài giây. Tôi biết kế hoạch truy vấn là tốt, nhưng SQL Server sẽ chỉ chọn kế hoạch đó khi chỉ có một số lượng nhỏ hàng - bất kỳ số lượng hàng lớn nào trong bản cập nhật của tôi sẽ dẫn đến kế hoạch tối ưu phụ.
Tôi nghĩ rằng sự song song có thể là đáng trách, vì vậy tôi đã đặt MAXDOP 1
ra truy vấn, nhưng không có kết quả - bước đó không còn nữa, nhưng sự lựa chọn / hiệu suất kém thì không. Tôi cũng sp_updatestats
vừa mới chạy sáng nay để đảm bảo đó không phải là nguyên nhân.
Tôi đã đính kèm hai kế hoạch thực hiện - kế hoạch ngắn hơn cũng nhanh hơn. Ngoài ra, đây là truy vấn được đề cập (đáng lưu ý rằng CHỌN tôi đã đưa vào dường như nhanh chóng trong các trường hợp cả số lượng hàng nhỏ và lớn):
update top (10000) FactSubscriberUsage3
set AccountID = sma.CustomerID
--select top 50 f.AccountID, sma.CustomerID
from FactSubscriberUsage3 f
join dimTime t
on f.TimeID = t.TimeID
join #mac sma
on f.macid = sma.macid
and t.TimeValue between sma.StartDate and sma.enddate
where f.AccountID = 0 --There's a filtered index on the table for this
Có bất cứ điều gì rõ ràng trong cách tôi thiết lập truy vấn của mình hoặc trong kế hoạch thực hiện với điều kiện sẽ tự cho mình lựa chọn xấu mà công cụ truy vấn đang thực hiện không? Nếu cần, tôi cũng có thể bao gồm các định nghĩa bảng liên quan và các chỉ mục được xác định trên chúng.
Đối với những người yêu cầu phiên bản chỉ thống kê của các đối tượng cơ sở dữ liệu: Tôi thậm chí không nhận ra bạn có thể làm điều đó, nhưng nó hoàn toàn có ý nghĩa! Tôi đã cố gắng tạo các tập lệnh cho cơ sở dữ liệu chỉ thống kê để người khác có thể tự kiểm tra các kế hoạch thực hiện, nhưng tôi có thể tạo các số liệu thống kê / biểu đồ trên chỉ mục được lọc của mình (có vẻ như lỗi cú pháp trong tập lệnh) hết may mắn đấy Tôi đã cố gắng loại bỏ bộ lọc và các kế hoạch truy vấn đã gần, nhưng không hoàn toàn giống nhau và tôi không muốn gửi bất kỳ ai theo đuổi ngỗng.
Cập nhật và một số kế hoạch thực hiện đầy đủ hơn: Trước hết, Plan Explorer của SQL Sentry là một công cụ đáng kinh ngạc. Tôi thậm chí không biết nó tồn tại cho đến khi xem các câu hỏi khác của kế hoạch truy vấn trên trang web này và có khá nhiều điều để nói về cách các truy vấn của tôi đang thực hiện. Mặc dù tôi không chắc cách giải quyết vấn đề, họ đã nói rõ vấn đề là gì.
Dưới đây là tóm tắt cho 10, 100 và 1000 hàng - bạn có thể thấy rằng truy vấn 1000 hàng là cách, không phù hợp với các hàng khác:
Bạn có thể thấy rằng truy vấn thứ ba có số lần đọc vô lý, vì vậy rõ ràng nó đang làm một cái gì đó hoàn toàn khác. Đây là kế hoạch thực hiện ước tính, với số lượng hàng. Kế hoạch thực hiện ước tính 1000 hàng:
Và đây là kết quả thực tế của kế hoạch thực hiện (nhân tiện, "không bao giờ kết thúc", hóa ra tôi có nghĩa là "kết thúc trong một giờ"). Kế hoạch thực hiện 1000 hàng
Điều đầu tiên tôi nhận thấy là, thay vì kéo 60K hàng từ bảng dimTime như dự kiến, nó thực sự kéo 1,6 tỷ, với B . Nhìn vào truy vấn của tôi, tôi không chắc chắn làm thế nào nó lấy lại được nhiều hàng từ bảng dimTime. Toán tử BETweEN tôi đang sử dụng chỉ đảm bảo rằng tôi lấy bản ghi chính xác từ #mac dựa trên bản ghi thời gian trong bảng Fact. Tuy nhiên, khi tôi thêm một dòng vào mệnh đề WHERE nơi tôi lọc t.TimeValue (hoặc t.TimeID) thành một giá trị duy nhất, tôi có thể cập nhật thành công 100.000 hàng trong vài giây. Do đó, và như đã nói rõ trong các kế hoạch thực hiện mà tôi đưa vào, rõ ràng bảng thời gian của tôi là vấn đề, nhưng tôi không chắc mình đã thay đổi tiêu chí tham gia như thế nào để giải quyết vấn đề này và duy trì độ chính xác . Có suy nghĩ gì không?
Để tham khảo, ở đây kế hoạch (có số lượng hàng) cho bản cập nhật 100 hàng. Bạn có thể thấy rằng nó đạt cùng một chỉ mục và vẫn có hàng tấn hàng, nhưng không nơi nào có cùng mức độ của một vấn đề. Thực hiện 100 hàng với số lượng hàng :
from #mac sma join f on f.macid = sma.macid join dimTime t on f.TimeID = t.TimeID and t.TimeValue between sma.StartDate and sma.enddate
vsfrom #mac join t on t.TimeValue between sma.StartDate and sma.enddate join f on f.TimeID = t.TimeID and f.macid = sma.macid
TOP 50
vẫn nên thực hiện nhanh chóng. Bạn có thể tải lên các kế hoạch XML? Tôi cần nhìn vào số lượng hàng. Bạn có thể chạy TOP 50
với maxdop 1 và dưới dạng chọn, không phải là bản cập nhật và đăng kế hoạch không? (Cố gắng đơn giản hóa / chia đôi không gian tìm kiếm).
t.TimeValue between sma.StartDate and sma.enddate
có thể sẽ tạo ra nhiều hàng vô dụng hơn mà sau đó được lọc ra trong liên kết với FactSubscacker và do đó không kết thúc cuối cùng.
sp_updatestatistics
trên bàn?