Використання покривають індексів
Не завжди потрібно, щоб при використанні некластерізованних індексів SQL Server на другому етапі витягував всю рядок. Ця ситуація виникає, коли некластерізованний індекс включає всі дані таблиці, які потрібно SQL Server для виконання операції. Коли це відбувається, ми називаємо індекс покриває, тому що цей індекс покриває весь запит. Покривають індекси можуть істотно збільшити продуктивність запиту; в цьому легко переконатися на двох планах запитів з попереднього прикладу. У таких запитах вартість операторів, які витягають потрібні рядки даних, становить 97% всієї вартості запиту. Іншими словами, запит без цієї операції буде виконано в 32 рази швидше. Давайте розглянемо, як працюють покривають індекси.
Застосовуємо покривають індекси
- Запустіть SQL Server Management Studio, Відкрийте вікно New Query (Створити запит) і змініть контекст бази даних на Adventure Works.
- Ідея покривають індексів полягає в тому, що вони містять всі дані, необхідні для виконання запитів. Якщо ми подивимося на перший з таких запитів, який вже використовувався в попередньому прикладі, то побачимо, що SQL Server потрібні стовпці SalesOrderID. CarrierTrackingNumber і ProductID.
Некластерізованний індекс NCLIX_OrderDetails_ProductID. який ми створили раніше, включає стовпець ProductID. оскільки він побудований на цьому стовпці, а також стовпець SalesOrderID. оскільки цей стовпець є ключовим стовпцем кластерізованного індексу. Тому SalesOrderID є покажчиком, який SQL Server використовує в некластерізованний індексі. Отже, сервера SQL Server, щоб отримати CarrierTrackingNumber. потрібно повернути рядки даних, виконавши пошук (метод seek) тільки по кластерізованний індексу. У другому запиті стовпчика CarrierTrackingNumber немає в списку SELECT. Введіть і виконайте інструкцію, включивши дійсний план виконання, щоб побачити різницю. Код цього прикладу є в файлах прикладів під ім'ям Using Covered Indexes.sql.
На малюнку, показаному нижче, видно, що сервера SQL Server для виконання другого запиту потрібно звернутися до кластерізованний індексу, тому що індекс покриває запит, якщо стовпець CarrierTrackingNumber не вибрано. Оскільки доступ до кластерізованний індексу для кожного рядка дуже дорого коштує, другий запит становить лише 1% від загальної вартості пакета. Подивившись на вкладку Messages (Повідомлення), ми бачимо, що для того. щоб покрити запит, SQL Server потрібно виконати тільки 2 зчитування сторінки (замість 709 зчитувань, необхідних для першого запиту).
Ви переконалися, що покриває індекс може дати великий виграш в швидкості виконання. Звичайно, неможливо видалити стовпці з запиту, якщо вони потрібні в результаті. Але за загальним правилом слід витягувати тільки ті стовпці, які вам дійсно потрібні, щоб зробити більш вірогідним застосування покриває індексу. Не слід використовувати в інструкції SELECT символ зірочки (*) тільки тому, що так простіше скласти запит.
Поглянувши на план виконання, ви побачите, що доступ до кластерізованний індексу більше не потрібен. На вкладці повідомлень видно, що для виконання цього запиту тепер потрібно тільки 5 зчитувань сторінок, тоді як раніше було потрібно 709.
Примітка. Включені стовпці викликають перевантаження сервера SQL Server при зміні даних, тому що SQL Server доводиться змінювати кожен індекс і ще тому, що для їх зберігання потрібно більше місця в файлах даних. Отже, включення стовпців в некластерізованний індекси - це хороший спосіб підвищення продуктивності запитів, але не слід створювати індекси з включенням стовпців для всіх запитів в додатку. Цю функцію слід використовувати виключно для прискорення виконання проблемних запитів.
Індекси в обчислюваних шпальтах
У таблиці dbo.OrderDetails у нас є обчислюваний стовпець LineTotal. який представляє значення LineTotal для рядка і обчислюється за такою формулою: