Bao cát
Trong khi làm việc trên Top Chất lượng Blog Posts®, tôi đi qua một số hành vi ưu tôi thấy thực sự phẩn nộ thú vị. Tôi không có lời giải thích ngay lập tức, ít nhất không phải là một người tôi hài lòng, vì vậy tôi sẽ đưa nó vào đây trong trường hợp ai đó thông minh xuất hiện.
Nếu bạn muốn theo dõi, bạn có thể lấy phiên bản 2013 của kết xuất dữ liệu Stack Overflow tại đây . Tôi đang sử dụng bảng Nhận xét, với một chỉ mục bổ sung trên đó.
CREATE INDEX [ix_ennui] ON [dbo].[Comments] ( [UserId], [Score] DESC );
Truy vấn một
Khi tôi truy vấn bảng như vậy, tôi nhận được một kế hoạch truy vấn kỳ lạ .
WITH x
AS
(
SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
ORDER BY c.Score DESC
)
SELECT *
FROM x
WHERE x.Score >= 500;
Vị từ SARGable trên Điểm không được đẩy vào bên trong CTE. Đó là trong một toán tử lọc nhiều sau đó trong kế hoạch.
Mà tôi thấy kỳ lạ, vì ORDER BY
trên cùng một cột với bộ lọc.
Truy vấn hai
Nếu tôi thay đổi truy vấn, nó sẽ bị đẩy.
WITH x
AS
(
SELECT c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
)
SELECT TOP 101 *
FROM x
WHERE x.Score >= 500
ORDER BY x.Score DESC;
Các kế hoạch truy vấn thay đổi , quá, và chạy nhanh hơn nhiều, không có tràn vào đĩa. Cả hai đều tạo ra kết quả giống nhau, với vị từ khi quét chỉ mục không bao gồm.
Truy vấn ba
Điều này tương đương với việc viết truy vấn như vậy:
SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
WHERE c.Score >= 500
ORDER BY c.Score DESC;
Truy vấn bốn
Sử dụng bảng dẫn xuất sẽ có cùng một kế hoạch truy vấn "xấu" như truy vấn CTE ban đầu
SELECT *
FROM ( SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
ORDER BY c.Score DESC ) AS x
WHERE x.Score >= 500;
Mọi thứ trở nên kỳ lạ hơn khi ...
Tôi thay đổi truy vấn để sắp xếp dữ liệu tăng dần và bộ lọc thành <=
.
Để tránh làm cho câu hỏi này quá dài, tôi sẽ đặt mọi thứ lại với nhau.
Truy vấn
--Derived table
SELECT *
FROM ( SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
ORDER BY c.Score ASC ) AS x
WHERE x.Score <= 500;
--TOP inside CTE
WITH x
AS
(
SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
ORDER BY c.Score ASC
)
SELECT *
FROM x
WHERE x.Score <= 500;
--Written normally
SELECT TOP 101
c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
WHERE c.Score <= 500
ORDER BY c.Score ASC;
--TOP outside CTE
WITH x
AS
(
SELECT c.UserId, c.Text, c.Score
FROM dbo.Comments AS c
)
SELECT TOP 101 *
FROM x
WHERE x.Score <= 500
ORDER BY x.Score ASC;
Các kế hoạch
Lưu ý rằng không có truy vấn nào trong số các truy vấn này tận dụng chỉ mục không bao gồm - điều duy nhất thay đổi ở đây là vị trí của toán tử bộ lọc. Trong mọi trường hợp là vị từ được đẩy đến truy cập chỉ mục.
Một câu hỏi xuất hiện!
Có một lý do mà một vị từ SARGable có thể được đẩy trong một số tình huống và không phải trong các tình huống khác? Sự khác biệt trong các truy vấn được sắp xếp theo thứ tự giảm dần rất thú vị, nhưng sự khác biệt giữa những truy vấn và những thứ đang tăng dần kỳ quái.
Đối với bất kỳ ai quan tâm, đây là các kế hoạch chỉ có một chỉ mục trên Score
: