Tại sao mệnh đề WHERE của tôi được hưởng lợi từ một cột được bao gồm trong cộng đồng?


12

Theo câu trả lời này , trừ khi một chỉ mục được xây dựng trên các cột được sử dụng để hạn chế, truy vấn sẽ không được hưởng lợi từ một chỉ mục.

Tôi có định nghĩa này:

CREATE TABLE [dbo].[JobItems] (
    [ItemId]             UNIQUEIDENTIFIER NOT NULL,
    [ItemState]          INT              NOT NULL,
    [ItemPriority]       INT NOT NULL,
    [CreationTime]       DATETIME         NULL DEFAULT GETUTCDATE(),
    [LastAccessTime]     DATETIME         NULL DEFAULT GETUTCDATE(),
     -- other columns
 );

 CREATE UNIQUE CLUSTERED INDEX [JobItemsIndex]
    ON [dbo].[JobItems]([ItemId] ASC);
 GO

CREATE INDEX [GetItemToProcessIndex]
    ON [dbo].[JobItems]([ItemState], [ItemPriority], [CreationTime])
    INCLUDE (LastAccessTime);
GO

và truy vấn này:

UPDATE TOP (150) JobItems 
SET ItemState = 17 
WHERE 
    ItemState IN (3, 9, 10)
    AND LastAccessTime < DATEADD (day, -2, GETUTCDATE()) 
    AND CreationTime < DATEADD (day, -2, GETUTCDATE());

Tôi đã xem xét kế hoạch thực tế và chỉ có một chỉ mục tìm kiếm với vị từ chính xác như trong WHERE- không có "tra cứu dấu trang" bổ sung nào để truy xuất LastAccessTimengay cả khi chỉ mục sau được "đưa" vào chỉ mục, không phải là một phần của chỉ mục.

Đối với tôi có vẻ như hành vi này mâu thuẫn với quy tắc rằng cột phải là một phần của chỉ mục và không chỉ là "bao gồm".

Là hành vi tôi quan sát đúng? Làm cách nào tôi có thể biết trước nếu WHERElợi ích của tôi từ một cột được bao gồm hoặc cần cột là một phần của chỉ mục?


Nó vẫn có thể tìm kiếm dựa trên ItemStategiá trị, tuy nhiên Seek sẽ không hiệu quả như thể Index của bạn được cấu trúc như sau(ItemState, CreationTime, LastAccessTime)
Mark Sinkinson 17/8/2015

1
@MarkSinkinson hoặc chỉ(ItemState, CreationTime) INCLUDE (LastAccessTime)
ypercubeᵀᴹ

@sharptooth câu trả lời được liên kết mà bạn không nói rằng ("trừ khi một chỉ mục được xây dựng trên các cột được sử dụng để hạn chế truy vấn sẽ không được hưởng lợi từ một chỉ mục"). Nó nói rằng một chỉ mục trên (a,b)không phải là tốt nhất cho một truy vấn SELECT a FROM t WHERE b=5;và rằng một chỉ mục trên (b) INCLUDE (a)là tốt hơn nhiều.
ypercubeᵀᴹ

Câu trả lời:


9

Vị ngữ của bạn khác với Vị ngữ tìm kiếm của bạn.

Tìm kiếm Vị ngữ được sử dụng để tìm kiếm dữ liệu theo thứ tự trong chỉ mục. Trong trường hợp này, nó sẽ thực hiện ba lần tìm kiếm, một lần cho mỗi ItemState mà bạn quan tâm. Ngoài ra, dữ liệu theo thứ tự ItemP Warriority, do đó không thể thực hiện thao tác "Tìm kiếm" nào nữa.

Nhưng trước khi dữ liệu được trả về, nó sẽ kiểm tra mọi hàng bằng cách sử dụng Vị ngữ, mà tôi gọi là Vị ngữ dự phòng. Nó được thực hiện dựa trên kết quả của Dự đoán Tìm kiếm.

Bất kỳ cột được bao gồm nào không phải là một phần của dữ liệu được đặt hàng, nhưng có thể được sử dụng để đáp ứng Dự đoán dư, mà không phải thực hiện Tra cứu bổ sung.

Bạn có thể thấy tài liệu tôi đã viết về điều này xung quanh Sargability. Kiểm tra phiên tại SQLBits nói riêng, tại http://bit.ly/Sargability

Chỉnh sửa: Để hiển thị tác động của Residuals tốt hơn, hãy chạy truy vấn bằng cách sử dụng không có giấy tờ OPTION (QUERYTRACEON 9130), phần này sẽ tách rời Residual thành một toán tử Bộ lọc riêng biệt (thực sự là phiên bản trước của kế hoạch trước khi phần dư được chuyển vào toán tử Seek). Nó cho thấy rõ tác động của Tìm kiếm không hiệu quả, bằng số lượng hàng được chuyển sang trái cho Bộ lọc.

Cũng đáng lưu ý rằng vì mệnh đề IN trên ItemState, dữ liệu được truyền sang trái thực sự là theo thứ tự ItemState, không phải theo thứ tự ItemP Warriority. Một chỉ mục tổng hợp trên ItemState được theo sau bởi một trong những ngày (ví dụ: (ItemState, LastAccessTime)) có thể được sử dụng để có ba Tìm kiếm (chú ý Tìm kiếm dự đoán hiển thị ba tìm kiếm trong một toán tử Seek), mỗi lần tìm hai mức, tạo ra dữ liệu vẫn theo thứ tự ItemState (ví dụ, ItemState = 3 và LastAccessTime ít hơn một cái gì đó, sau đó ItemState = 9 và LastAccessTime ít hơn một cái gì đó, và sau đó ItemState = 10 và LastAccessTime ít hơn một cái gì đó).

Một chỉ mục trên (ItemState, LastAccesTime, CreationTime) sẽ không hữu ích hơn một chỉ số trên (ItemState, LastAccessTime) vì mức CreationTime chỉ hữu ích nếu Seek của bạn dành cho kết hợp ItemState và LastAccessTime cụ thể, không phải là một phạm vi. Giống như cách danh bạ điện thoại không theo thứ tự FirstName nếu bạn quan tâm đến Tên họ bắt đầu ở F.

Nếu bạn muốn có một chỉ mục tổng hợp nhưng bạn sẽ không bao giờ có thể sử dụng các cột sau trong Tìm kiếm dự đoán vì cách bạn sử dụng các cột trước đó, thì bạn cũng có thể có chúng như các cột được bao gồm, trong đó chúng chiếm ít không gian hơn trong chỉ mục (vì chúng chỉ được lưu trữ ở cấp độ lá của chỉ mục, không phải ở cấp cao hơn) nhưng vẫn có thể tránh tra cứu và được sử dụng trong các vị từ dư.

Theo thuật ngữ Dự đoán còn lại - đó là thuật ngữ của riêng tôi đối với tài sản này của Người tìm kiếm. Hợp nhất Tham gia một cách rõ ràng gọi nó là Dự đoán dư thừa tương đương và Kết hợp băm gọi nó là một phần dư thăm dò (mà bạn có thể nhận được từ TSA nếu bạn khớp với hàm băm). Nhưng trong Seek, họ chỉ gọi nó là Vị ngữ khiến nó dường như ít tệ hơn nó.


3

GetItemToProcess Index không hoàn toàn có thể tìm kiếm được vì mệnh đề where của bạn được bật ItemState + LastAccessTime + CreationTime. Các cột được lập chỉ mục và mệnh đề where là một kết hợp không hoàn hảo.

Nếu bạn tạo một chỉ số bao phủ trên ItemState + LastAccessTime + CreationTime, đối với mỗi trận đấu bạn nhận được từ GetItemToProcess Index, bạn cũng nhận được giá trị của Khóa chính (ItemId). Nó chỉ phải đảm bảo rằng ngày thứ 2 là một trận đấu.

Đây là tất cả những gì bạn cần sau đó nhảy đến vị trí của hàng trên trang của nó và cập nhật nó.

Với chỉ mục hiện tại của bạn, nó có thể giúp máy chủ tìm các hàng với ItemState mà bạn muốn nhưng sau đó vẫn phải đọc tất cả chúng từ chỉ mục để tìm kết quả khớp chính xác trên LastAccessTime + CreationTime. Tùy thuộc vào các vị từ ngày và kích thước của tập hợp khớp và những gì phải loại trừ, nó có thể dẫn đến nhiều IO hơn chỉ số bao phủ hoàn hảo trên 3 cột chỉ tìm kiếm ItemState và cột thứ hai (ngày được lập chỉ mục thứ nhất) . Ngày thứ hai trong chỉ mục có thể được bao gồm mặc dù. Các cột bổ sung không nên được lập chỉ mục giữa 3 cột này mặc dù nó có thể ổn với tư cách là cột thứ 4 (xem câu trả lời của cướp về các cột phụ).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.