Bất kỳ lý do để có cả một chỉ mục với các cột bao gồm và một không có?


7

Tôi đang xem qua một vài truy vấn chạy chậm trên cơ sở dữ liệu đã được phát triển đáng kể (dưới một số nhà phát triển khác nhau) trong vài năm qua.
Một trong những bảng được sử dụng phổ biến nhất có một vài chỉ mục với các cột được lập chỉ mục giống nhau, nhưng một bảng sẽ bao gồm các cột và các bảng khác thì không.

Ví dụ:
Một chỉ mục:

 CREATE NONCLUSTERED INDEX [IDX_tblTable_IndexedColumnId_Inc] ON [dbo].[tblTable]
 (
[IndexedColumnId] ASC
 )

Và sau đó:

CREATE NONCLUSTERED INDEX [IDX_tblTable_IndexedColumnId_Inc] ON [dbo].[tblTable]
(
[IndexedColumnId] ASC
)
INCLUDE (   [Field1Id],
[Field2],
[Field3],
[Field4],
[Field5],
[Field6]) 

Tôi cho rằng đây chỉ là một giám sát và chỉ sử dụng hết dung lượng đĩa và chi phí bổ sung để có chỉ mục mà không có các cột được bao gồm (các cột được bao gồm là cần thiết).

Có bất kỳ lợi ích nào khi có hai chỉ mục trên cùng một cột, một chỉ mục có các cột được bao gồm và một chỉ mục không có?

Câu trả lời:


8

Để mở rộng một chút về những gì tương tự n chiều yêu thích của mọi người đã nhận xét, có thể có một số lợi ích khi có cả hai.

Đây là một bản demo nhỏ (nhưng không đầy đủ).

Sự cần thiết:

USE StackOverflow;
SET NOCOUNT ON; 

CREATE TABLE dbo.IndexCrap
(
    Id INT IDENTITY PRIMARY KEY CLUSTERED,
    Whatever DATETIME,
    Nonsense VARCHAR(50),
    Etc UNIQUEIDENTIFIER,
    SoForth BIT
);

INSERT dbo.IndexCrap WITH (TABLOCK)
        (Whatever, Nonsense, Etc, SoForth )
SELECT TOP 1000 DATEADD(DAY, x.n, GETDATE()),
                REPLICATE('A', x.n % 50),
                NEWID(),
                CASE WHEN x.n % 15 = 0 THEN 1 ELSE 0 END
FROM (SELECT ROW_NUMBER() OVER (ORDER BY @@ROWCOUNT) AS n
        FROM sys.messages AS m ) AS x;

Các chỉ mục:

CREATE INDEX ix_tinydancer ON dbo.IndexCrap (Whatever);

CREATE INDEX ix_largemarge ON dbo.IndexCrap (Whatever) INCLUDE (Nonsense, Etc, SoForth);

Vì vậy, giống như câu hỏi của bạn, về chỉ mục trên một cột, một chỉ mục trên cùng một cột với một số bao gồm.

Các truy vấn:

SELECT COUNT(*)
FROM dbo.IndexCrap AS ic;

SELECT ic.Nonsense, ic.Etc, ic.SoForth
FROM dbo.IndexCrap AS ic
WHERE ic.Whatever >= DATEADD(DAY, 500, GETDATE());

Các kế hoạch thực hiện:

Đối với COUNT(*)truy vấn, trình tối ưu hóa chọn chỉ mục cột đơn nhỏ nhất của chúng tôi trên chỉ mục không bao gồm rộng hơn và chỉ mục cụm rộng hơn một chút, vì nó không được lọc và tất cả những gì chúng ta cần là số lượng hàng.

QUẢ HẠCH

Đối với truy vấn rộng hơn, trình tối ưu hóa chọn chỉ mục che phủ để không phải a) quét chỉ mục được nhóm hoặc b) truy cập vào chỉ mục hẹp hơn và thực hiện Tìm kiếm khóa trở lại chỉ mục được nhóm.

QUẢ HẠCH

Tất nhiên, bạn có thể không biết mọi truy vấn duy nhất chạy trên hệ thống của mình. Đó là lý do tại sao công ty tôi làm việc để viết sp_BlitzIndex, một công cụ miễn phí để phân tích các chỉ mục của bạn .

Nếu chúng tôi chạy EXEC master.dbo.sp_BlitzIndex @DatabaseName = 'StackOverflow', @Mode = 4;, đây là một số kết quả mà chúng tôi quan tâm:

QUẢ HẠCH

Hai chỉ mục tôi đã thêm vào IndexCrap(không tính PK / CX) được gắn cờ là có các cột khóa trùng lặp. Nó cũng đưa ra định nghĩa, cách sử dụng, kích thước và nhiều thứ khác không được hiển thị trong screencap.

Các quầy sử dụng không hoàn hảo. Họ sẽ đặt lại nếu bạn thêm hoặc xóa chỉ mục, trong một số phiên bản SQL Server, họ sẽ đặt lại nếu bạn xây dựng lại chỉ mục và tất nhiên họ sẽ đặt lại nếu bạn khởi động lại SQL Server.

Hi vọng điêu nay co ich!

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.