У таблиці Retailer_Relations є наступний складений індекс ПК та запропонований індекс-
Хоча пропущені індекси можуть бути корисними і, безумовно, можуть працювати, я б не витрачав занадто багато часу на відсутні індекси, ці підказки створюються на оціночному плані виконання, а не на фактичному плані виконання.
Точніше, ці підказки засновані на передумові зниження вартості Query Bucks ™, що використовується операторами в плані. Оптимізатор обчислює розрахункові витрати та додає відповідні підказки про відсутність.
В результаті вони можуть помилитися. Якщо ви не впевнені, чи збираєтеся допомогти, найкраще - перевірити ситуацію до і після. Ви можете зробити це, додавши заяву
SET STATISTICS IO, TIME ON;
перед запуском запиту.
Крім того, ви можете використовувати статистичний аналізатор, щоб полегшити читання цих статистичних даних.
Це може бути через порядок стовпців в індексі?
Це правильно, створення відсутніх індексів може покращити вибірковість запитів, наприклад, якщо ваш запит виглядає так:
SELECT RelatedRetailerID
FROM Retailer_Relations
WHERE
RetailerID = 5 AND
RelationType = 20;
або так:
SELECT RelatedRetailerID
FROM Retailer_Relations
ORDER BY
RetailerID,
RelationType;
Причина цього полягає в тому, що обидва індекси можуть шукати в RetailerID, і ця частина не збирається змінюватися. Але що робити, якщо на RelationType застосовані додаткові фільтри / замовлення? Це було б повсюдно в кластерному індексі, внаслідок чого воно було б третім ключовим значенням, а не другим ключовим значенням. І як ми знаємо, це є другим ключовим значенням у NCI.
Гаразд, але коли або як некластеризований індекс покращить запит?
Кілька випадків можуть бути:
- Якщо відношення типу фільтрує багато значень, залишковий введення / виведення може бути високим, що призводить до можливої потреби в некластеризованому індексі (запит №1)
- Впорядкування в двох стовпцях відбувається (Один спосіб), а набір результатів великий (Запит №2).
- Як зазначав @AaronBertrand: якщо різниця розмірів CI порівняно з NCI становить значну кількість, додавання NCI зменшить кількість прочитаних сторінок за запитами, які користуються нею.
Примітка стороні NCI
В якості додаткового зауваження, додавання стовпців клавіш до списку включення у вашій NCI точно не потрібно, оскільки стовпці ключів CI автоматично включаються до всіх некластеризованих індексів.
Ви можете зробити це, якщо ви не впевнені, що кластерний індекс залишиться тим самим, і хочете, щоб стовпець завжди включався.
Що стосується самого запиту, якщо ви додали план виконання через PasteThePlan, ми могли б дати трохи більше інформації про індексацію / покращення запиту.
Тестування
Створіть таблицю і додайте кілька рядків
CREATE TABLE Retailer_Relations (
RetailerID int ,
RelatedRetailerID int ,
RelationType smallint,
CreatedOn datetime,
CONSTRAINT PK_Retailer_Relations
PRIMARY KEY CLUSTERED (
RetailerID ASC,
RelatedRetailerID ASC,
RelationType ASC
) ON [PRIMARY])
DECLARE @I Int = 1
WHILE @I < 1000
BEGIN
INSERT INTO Retailer_Relations(RetailerID,RelatedRetailerID,RelationType,CreatedOn)
VALUES(@I,@I,@I,GETDATE()
)
set @I += 1
END
Запит №1
SELECT RelatedRetailerID
FROM Retailer_Relations
WHERE
RetailerID = 5 AND
RelationType = 20;
План без індексу Тут
Поки він робить пошук, він робить пошук на RetailerID. Після цього він видає залишковий предикат вводу / виводу на RelationType
Додайте індекс
CREATE NONCLUSTERED INDEX IX_TEST
ON Retailer_Relations (
RetailerID,
RelationType
)
INCLUDE (
RelatedRetailerID
)
Залишковий предикат зник, усе відбувається в предикаті пошуку в обох стовпцях.
План виконання
З другим запитом додана допоміжна індекс стає ще більш очевидною:
SELECT RelatedRetailerID
FROM Retailer_Relations
ORDER BY
RetailerID,
RelationType;
Плануйте без індексу з оператором Сортування:
Плануйте за допомогою індексу, за допомогою індексу видаляється оператор сортування