Я вирішив трохи розібратися в цьому питанні, і я виявив кілька цікавих документів, які розповідають про те, як і коли використовувати, а може, краще, не (змушувати) використовувати некластеризований індекс.
Як підказано за коментарями Джона Ейсбренера , однією з найпопулярніших, навіть в інших блогах, є ця цікава стаття Кімберлі Л. Тріпп:
але це не єдине, якщо вам це цікаво, ви можете переглянути ці сторінки:
Як бачимо, всі вони рухаються навколо концепції пункту переломлення .
Цитується з статті KL Tripp
Що таке переломний момент?
Це момент, коли кількість повернутих рядків " вже не є достатньо вибірковою ". SQL Server вибирає НЕ використовувати некластеризований індекс для пошуку відповідних рядків даних і замість цього виконує сканування таблиці.
Коли SQL Server використовує некластеризований індекс на купі, в основному він отримує список покажчиків на сторінки базової таблиці. Потім він використовує ці покажчики для отримання рядків за допомогою ряду операцій під назвою Рядок пошуку ідентифікаторів рядків (RID). Це означає, що принаймні, воно буде використовувати стільки прочитаних сторінок, скільки кількість повернених рядків і, можливо, більше. Процес дещо схожий з кластерним індексом, як базова таблиця, з тим самим результатом: більше читає.
Але коли виникає ця переломна точка?
Звичайно, як і більшість речей у цьому житті, це залежить ...
Ніяк серйозно, це становить від 25% до 33% від кількості сторінок у таблиці, залежно від кількості рядків на сторінці. Але є кілька факторів, які слід враховувати:
Цитується з статті ITPRoToday
Інші фактори, що впливають на точку відкидання Хоча вартість пошуку RID є найважливішим фактором, який впливає на точку відхилення, є ряд інших факторів:
- Фізичний введення / виведення набагато ефективніше при скануванні кластерного індексу. Кластерні дані індексу послідовно розміщуються на диску в порядку індексу. Отже, на диску дуже мало бічного руху голови, що покращує продуктивність вводу / виводу.
- Коли двигун бази даних сканує кластерний індекс, він знає, що існує велика ймовірність того, що наступні кілька сторінок дискової доріжки все ще містять необхідні йому дані. Таким чином, він починає читати вперед в шматки 64 КБ замість звичайних сторінок 8 КБ. Це також призводить до швидшого вводу / виводу.
Тепер, якщо я знову виконую запити, використовуючи статистику IO:
SET STATISTICS IO ON;
SELECT id, foo, bar, nki FROM my_table WHERE nki < 20000 ORDER BY nki ;
SET STATISTICS IO OFF;
Logical reads: 312
SET STATISTICS IO ON;
SELECT id, foo, bar, nki FROM my_table WITH(INDEX(IX_my_TABLE));
SET STATISTICS IO OFF;
Logical reads: 41293
Другий запит потребує більш логічних читань, ніж перший.
Чи слід уникати некластеризованого індексу?
Ні, кластерний індекс може бути корисним, але варто витратити час і докласти додаткових зусиль, аналізуючи те, чого ви намагаєтеся досягти з ним.
Цитується з статті KL Tripp
Отже, що вам робити? Це залежить. Якщо ви добре знаєте свої дані і ви робите обширне тестування, ви можете розглянути можливість використання підказки (є кілька розумних речей, які ви можете програмно зробити в sps, я спробую скоро присвятити пост цьому). Однак набагато кращим вибором (якщо це взагалі можливо) є розгляд покриття (це справді мій головний пункт :). У моїх запитах покриття нереально, тому що мої запити хочуть, щоб усі стовпці (злий SELECT *), але якщо ваші запити вужчі, і вони є першочерговими, вам краще з індексом покриття (у багатьох випадках) над натяком, оскільки індекс, який охоплює запит, ніколи не підказує.
Це відповідь на головоломку на даний момент, але, безумовно, є набагато більше, чим зануритися. Точка перекидання може бути дуже хорошою справою - і вона зазвичай працює добре. Але, якщо ви виявите, що ви можете примусити індекс і отримати кращу ефективність, можливо, захочете провести кілька розслідувань і побачити, чи це все. Потім подумайте, наскільки вірогідний натяк на допомогу, і тепер ви знаєте, де можна зосередитися.