Tôi có một cái bàn như thế này:
CREATE TABLE Updates
(
UpdateId INT NOT NULL IDENTITY(1,1) PRIMARY KEY,
ObjectId INT NOT NULL
)
Về cơ bản theo dõi cập nhật cho các đối tượng với một ID ngày càng tăng.
Người tiêu dùng của bảng này sẽ chọn một đoạn gồm 100 ID đối tượng riêng biệt, được sắp xếp theo thứ tự UpdateId
và bắt đầu từ một cụ thể UpdateId
. Về cơ bản, theo dõi nơi nó rời đi và sau đó truy vấn bất kỳ cập nhật nào.
Tôi thấy đây là một vấn đề tối ưu hóa thú vị vì tôi chỉ có thể tạo một kế hoạch truy vấn tối ưu tối đa bằng cách viết các truy vấn xảy ra để làm những gì tôi muốn do chỉ mục, nhưng không đảm bảo những gì tôi muốn:
SELECT DISTINCT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
Trong trường hợp @fromUpdateId
là một tham số thủ tục lưu trữ.
Với một kế hoạch:
SELECT <- TOP <- Hash match (flow distinct, 100 rows touched) <- Index seek
Do tìm kiếm trên UpdateId
chỉ mục đang được sử dụng, kết quả đã tốt đẹp và được sắp xếp từ ID cập nhật thấp nhất đến cao nhất như tôi muốn. Và điều này tạo ra một kế hoạch phân biệt dòng chảy , đó là những gì tôi muốn. Nhưng thứ tự rõ ràng là hành vi không được đảm bảo, vì vậy tôi không muốn sử dụng nó.
Thủ thuật này cũng dẫn đến cùng một kế hoạch truy vấn (mặc dù với TOP dư thừa):
WITH ids AS
(
SELECT ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
ORDER BY UpdateId OFFSET 0 ROWS
)
SELECT DISTINCT TOP 100 ObjectId FROM ids
Mặc dù, tôi không chắc chắn (và nghi ngờ là không) nếu điều này thực sự đảm bảo cho việc đặt hàng.
Một truy vấn tôi hy vọng SQL Server sẽ đủ thông minh để đơn giản hóa điều này, nhưng cuối cùng nó lại tạo ra một kế hoạch truy vấn rất tệ:
SELECT TOP 100 ObjectId
FROM Updates
WHERE UpdateId > @fromUpdateId
GROUP BY ObjectId
ORDER BY MIN(UpdateId)
Với một kế hoạch:
SELECT <- Top N Sort <- Hash Match aggregate (50,000+ rows touched) <- Index Seek
Tôi đang cố gắng tìm cách tạo ra một kế hoạch tối ưu với tìm kiếm chỉ mục UpdateId
và một luồng khác biệt để loại bỏ các bản sao ObjectId
. Có ý kiến gì không?
Dữ liệu mẫu nếu bạn muốn nó. Các đối tượng sẽ hiếm khi có nhiều hơn một bản cập nhật và hầu như không bao giờ có nhiều hơn một hàng trong một bộ 100 hàng, đó là lý do tại sao tôi sau một luồng khác biệt , trừ khi tôi không biết gì hơn? Tuy nhiên, không có gì đảm bảo rằng một đơn ObjectId
sẽ không có hơn 100 hàng trong bảng. Bảng có hơn 1.000.000 hàng và dự kiến sẽ tăng nhanh.
Giả sử người dùng này có một cách khác để tìm cái thích hợp tiếp theo @fromUpdateId
. Không cần phải trả lại nó trong truy vấn này.