Hãy nói rằng tôi có một bàn duy nhất
CREATE TABLE Ticket (
TicketId int NOT NULL,
InsertDateTime datetime NOT NULL,
SiteId int NOT NULL,
StatusId tinyint NOT NULL,
AssignedId int NULL,
ReportedById int NOT NULL,
CategoryId int NULL
);
Trong ví dụ TicketId
này là Khóa chính.
Tôi muốn người dùng có thể tạo các truy vấn "một phần đặc biệt" đối với bảng này. Tôi nói một phần vì một vài phần của truy vấn sẽ luôn được sửa:
- Truy vấn sẽ luôn thực hiện một bộ lọc phạm vi trên một
InsertDateTime
- Truy vấn sẽ luôn luôn
ORDER BY InsertDateTime DESC
- Truy vấn sẽ kết quả trang
Người dùng có thể tùy chọn lọc trên bất kỳ cột nào khác. Họ có thể lọc trên không, một hoặc nhiều. Và đối với mỗi cột, người dùng có thể chọn từ một tập hợp các giá trị sẽ được áp dụng dưới dạng phân tách. Ví dụ:
SELECT
TicketId
FROM (
SELECT
TicketId,
ROW_NUMBER() OVER(ORDER BY InsertDateTime DESC) as RowNum
FROM Ticket
WHERE InsertDateTime >= '2013-01-01' AND InsertDateTime < '2013-02-01'
AND StatusId IN (1,2,3)
AND (CategoryId IN (10,11) OR CategoryId IS NULL)
) _
WHERE RowNum BETWEEN 1 AND 100;
Bây giờ giả sử bảng có 100.000.000 hàng.
Điều tốt nhất tôi có thể đưa ra là một chỉ số bao gồm từng cột "tùy chọn":
CREATE NONCLUSTERED INDEX IX_Ticket_Covering ON Ticket (
InsertDateTime DESC
) INCLUDE (
SiteId, StatusId, AssignedId, ReportedById, CategoryId
);
Điều này cho tôi một kế hoạch truy vấn như sau:
- LỰA CHỌN
- Bộ lọc
- Hàng đầu
- Dự án trình tự (Tính toán vô hướng)
- Bộ phận
- Tìm kiếm chỉ mục
- Bộ phận
- Dự án trình tự (Tính toán vô hướng)
- Hàng đầu
- Bộ lọc
Có vẻ khá tốt. Khoảng 80% -90% chi phí đến từ hoạt động Tìm kiếm Index, rất lý tưởng.
Có chiến lược tốt hơn để thực hiện loại tìm kiếm này?
Tôi không nhất thiết muốn giảm tải bộ lọc tùy chọn cho khách hàng vì trong một số trường hợp, kết quả được đặt từ phần "cố định" có thể là 100 hoặc 1000 giây. Sau đó, khách hàng cũng chịu trách nhiệm phân loại và phân trang có thể làm việc quá nhiều cho khách hàng.
RowNum BETWEEN 101 AND 200
?