Tôi đang cố gắng xác định lý do tại sao trình tối ưu hóa truy vấn trong SQL Server khuyên bạn nên tạo một chỉ mục mới thay vì sử dụng một chỉ mục hiện có dường như là đủ cho truy vấn.
Đầu tiên là bàn. Tên cột thay đổi để bảo vệ người vô tội :-)
CREATE TABLE [myTable] (
[id] [int] IDENTITY(1,1) NOT NULL,
[serialNumber] [varchar](12) NOT NULL,
[sName] [varchar](64) NOT NULL,
[meanValue] [int] NOT NULL,
[range] [int] NOT NULL,
[modifiedDate] [datetime] NOT NULL,
CONSTRAINT [PK_myTable] PRIMARY KEY CLUSTERED ( [id] ASC )
)
Tạo chỉ mục trong câu hỏi:
CREATE NONCLUSTERED INDEX [IDX_myIndex]
ON [myTable] ([serialNumber], [sName], [meanValue], [range])
INCLUDE ([modifiedDate])
Thêm dữ liệu để kiểm tra bằng trình tạo lựa chọn của bạn ;-) Chạy truy vấn sau (bảng chỉ có vài triệu bản ghi)
SELECT TOP 1000
[serialNumber],
[sName],
[meanValue],
[range],
[modifiedDate]
FROM [myTable]
WHERE [serialNumber] = 137802
AND [sName] = 'A Name'
Trình tối ưu hóa truy vấn khuyên bạn nên sử dụng một chỉ mục mới trong đó bổ sung trong đó các mệnh đề được trình bày trong INCLUDE thay vì một phần của khóa:
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [dbo].[myTable] ([sName])
INCLUDE ([serialNumber],[meanValue],[range],[modifiedDate])
Tôi có ấn tượng rằng một chỉ mục rộng hơn bao gồm nhiều cột hơn sẽ được sử dụng làm chỉ mục miễn là thứ tự của các mệnh đề WHERE thể hiện thứ tự của các cột được lập chỉ mục.
Nếu tôi cũng WHERE trên sửa đổiData, chỉ mục sẽ được sử dụng và trình tối ưu hóa truy vấn không phàn nàn:
SELECT TOP 1000
[serialNumber],
[sName],
[meanValue],
[range],
[modifiedDate]
FROM [myTable]
WHERE [serialNumber] = 137802
AND [sName] = 'A Name'
AND ([modifiedDate] >= '2000-04-25' AND [modifiedDate] < '2019-04-30')
Liên kết DBA
SQL Server 2008R2 - Tại sao chỉ mục của tôi không được sử dụng cho thấy mối tương quan chặt chẽ hơn giữa khóa chỉ mục và bao gồm với câu lệnh SELECT giúp xác định sử dụng chỉ mục (nhưng trong ví dụ của tôi về cơ bản là giống nhau). Tôi có rất nhiều hàng, có thể thỏa mãn kiểm tra xác suất sử dụng hàng và không có NULL - do đó phủ nhận hiệu ứng NULL của chỉ mục.
Tôi nghĩ, có thể không chính xác, rằng một chỉ mục A, B, C, D
sẽ bao gồm một truy vấn trong đó A, B, C
, hoặc A, B
, hoặc A
sẽ được chạy. Là giả định này sai? Tôi nhận ra rằng có thể có những điều kiện cạnh tranh để loại bỏ khái niệm cơ bản này, nhưng ở mức độ cơ bản, đây không phải là cách nó hoạt động?
Cảm ơn trước bất kỳ sự giúp đỡ nào, chỉ ra sự ngu ngốc theo cách của tôi, nhận ra tôi cần phải quay lại trường DB, v.v ... :-)
IDX_myIndex
không sử dụng? Kế hoạch truy vấn thực tế là gì?
WHERE [serialNumber] = 137802
trong khi cột là một varchar. Tôi cá rằng đó là lý do cho những lời phàn nàn.
serialNumber
một varchar
trong những nơi đầu tiên nếu các giá trị nó chứa được số? Nếu nó luôn lưu trữ các giá trị số và các số 0 đứng đầu không đáng kể thì việc lưu trữ dưới dạng một kiểu số sẽ gọn hơn.
SerialNumber
và chỉ số khác làsName
. Ngoài ra, đối với các trường hợp hai chỉ mục có thể thỏa mãn một truy vấn như nhau và trong đó các chỉ mục về cơ bản có cùng kích thước, thì về cơ bản, đó là một xu lật cho SQL Server. Việc nó đề xuất một chỉ mục khác có lẽ có nghĩa là nó có thể đã sử dụng một kế hoạch khác (đây chỉ là một nhận xét vì tôi chưa xem xét chi tiết thực tế hoặc cố gắng để chế lại kịch bản của bạn).