Індексація від початку або коли виникає проблема продуктивності?


15

Моє запитання щодо використання індексів.

  1. Чи варто починати індексувати з самого початку або коли виникає проблема з продуктивністю?

  2. Ми також можемо створювати тимчасовий індекс під час виконання запиту. Які плюси і мінуси таких методик?

Відповіді:


17

Чи варто починати індексувати з самого початку або коли виникає проблема з продуктивністю?

Стратегія індексування, як правило, розвивається в міру появи моделей використання. З огляду на це, існують також стратегії та рекомендації щодо проектування, які можна застосувати наперед.

  • Виберіть хороший кластерний ключ . Зазвичай можна визначити відповідний кластерний індекс під час проектування, виходячи з очікуваного шаблону вставок до таблиці. Якщо переконливий випадок для зміни в майбутньому, так і нехай буде.

  • Створіть свої основні та інші унікальні обмеження . Вони виконуватимуться за допомогою унікальних індексів.

  • Створіть свої зовнішні ключі та пов’язані з ними некластеризовані індекси . Іноземні ключі - це ваші найпоширеніші стовпчики приєднання, тому індексуйте їх із самого початку.

  • Створіть індекси для будь-яких очевидно високоселективних запитів . Для моделей запитів, які ви вже знаєте, вони будуть вкрай вибірковими і, скоріш за все, використовуватимуть пошук, а не сканування.

Крім вищесказаного, використовуйте поступовий і цілісний підхід до впровадження нових індексів. Під цілісним я маю на увазі оцінку потенційної вигоди та впливу на всі запити та існуючі індекси при оцінці додавання.

Нечастою проблемою в колах SQL Server є перенапруження, як результат вказівок відсутнього індексу DMV та підказки SSMS. Жоден із цих інструментів не оцінює існуючі індекси, і з задоволенням запропонує вам створити новий індекс з 6 стовпцями, а не додати один стовпець до існуючого індексу з 5 стовпцями.

-- If you have this
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
)

-- But your query would benefit from the addition of a column
CREATE NONCLUSTERED INDEX [IX_MyTable_MyIndex] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

-- SSMS will suggest you create this instead
CREATE NONCLUSTERED INDEX [IX_MyTable_AnotherIndexWithTheSameColumnsAsTheExistingIndexPlusCol6] ON [dbo].[MyTable] 
(
    [col1] ASC
    , [col2] ASC
    , [col3] ASC
    , [col4] ASC
    , [col5] ASC
    , [col6] ASC
)

У Kimberly Tripp є чудовий матеріал про стратегію індексації, який, хоча зосереджений на SQL, застосовний до інших платформ. Для людей із SQL Server існує кілька зручних інструментів для ідентифікації дублікатів, як у наведеному вище прикладі.

Ми також можемо створювати тимчасовий індекс під час виконання запиту. Які плюси і мінуси таких методик?

Зазвичай це стосується лише рідко запущених запитів, як правило, ETL. Вам потрібно оцінити:

  1. Чи скорочує час, необхідний для створення індексу, час виконання запиту.
  2. Чи вагоміші витрати на те, щоб залишити індекс на місці, переважає час, необхідний для створення / падіння, коли це потрібно.

3
+1 Ключ кластеризації, Іноземний ключ, Унікальний / Первинний ключ та не довіряють пропущеним DMV-кодам індексу за номіналом ... Усі ці речі - чудова порада. Робота з існуючими індексами в SQL Server досить легко контролювати за допомогою DMV sys.dm_db_index_usage_stats. За певний проміжок часу ви можете перераховувати індекси, які не були відскановані чи не шукали, при цьому також бачите, що ці самі індекси були оновлені кілька разів. Це вказує на перенапруження.
Метт М

1
+1, однак "створити індекси для будь-яких очевидно високоселективних запитів". не охоплює всіх інших сценаріїв. Індекси можуть допомогти у сортуванні результатів, навіть якщо ваші запити не є вибірковими. Вони також можуть пришвидшити запити, якщо вони охоплюють усі вибрані стовпці.
Нерозумно

1
Домовились, але питання шукало стартову точку, а не кінцеву гру. Виявити запити для покриття складно без моделей використання, оскільки ви рідко можете охопити їх усі.
Марк Сторі-Сміт

8

Існують реальні ризики, пов'язані з обома підходами:

Варіант a) Індекс з самого початку, але не розуміючи, що ви створили ряд індексів, які ніколи не використовуються. Вони додають деякі накладні витрати (найбільш помітно до запитів, що змінюють дані, але також з оптимізацією операторів SELECT, що намагаються визначити найкращий індекс).

Вам потрібно буде дисциплінувати себе, щоб виявити індекси, які більше не використовуються, і спробувати їх видалити (PostgreSQL може це зробити; на жаль, MySQL порівняно дуже слабкий у цьому з поля).

Варіант b) Не додайте покажчики, поки люди не почнуть скаржитися, або якщо ваші діагностичні засоби не спричинить, що певні запити повільні та їх можна вдосконалити.

Ризик, який ви вводите, полягає в тому, що у вас немає достатньо великого часового вікна між тим, коли ви помітите, що вам потрібен індекс, і коли вам доведеться його додати.

PostgreSQL підтримує індекси побудови CONCURRENTLY, що дозволяє зменшити деякий стрес від цієї необхідності раптового додавання до індексу, але є деякі застереження, зазначені в посібнику.


Варіант (b), як правило, є моїм уподобанням, але я думаю, гібрид обох варіантів, мабуть, найкраще рішення. Це стосується вашого рівня довіри щодо того, чи вважаєте ви, що індекс буде використаний насправді.

Що робить це особливо складним обговоренням, це те, що зазвичай змінювати індекси легко, але змінити схему складніше. Я не хочу пропагувати затримку реакції b як привід бути необачним.


4

Окрім відповіді Марка

Ви можете відчути, отримавши реальні дані тесту в очікуваних кількостях. Я бачив багато, багато (занадто багато) випадків, коли запит працює в порядку з 1000 рядками, але не мільйон у виробництві.

Якщо ви можете, працюйте над копією продукції пізніше,

Звичайно, дивну проблему я бачив лише у виробництві через схеми використання, коли все інше тотожне

Тимчасові індекси? Поза моделями завантаження ETL, якщо вони вам знадобляться, вам вони знадобляться знову. Не забувайте: створення / падіння індексу - це запис і реєструється = більше завантаження


3

Просто додати кілька речей.

  • Тимчасові індекси - це жахлива ідея. Якщо індекс не знаходиться в тимчасовій таблиці.
  • Індекси займають набагато більше простору даних (як і інших накладних витрат), ніж люди розуміють. Тому створюйте їх консервативно.

Це мій підхід.

  1. Подібно до Марка, робіть індекси там, де вони мають сенс, але не прострочіть це.
  2. Вам не доведеться чекати, поки продуктивність не буде повільною для створення нових індексів. Кожен раз, коли ви пишете новий SQL, запустіть план запитів (бажано, проти вашої бази даних prod). Ви повинні мати змогу побачити, чи потрібен новий індекс.
  3. Не бійтеся поміщати > 0або вказувати > ""свої пропозиції про невикористані стовпці.

    1. Тобто скажімо, що у вас є індекс на A, B, C та D. Однак у вас є лише інформація A, B, D. Немає причини, щоб цього не зробити -
    select * from blah 
    where A="one" 
    and B="two" 
    and C>=""     --to match index
    and D="four"
    
    --This will use your existing index. No need to create a redundant one.

Інша справа, це на форумі "dba", але створення індексу дійсно повинно бути відповідальністю розробника, а не dba. (Для випадків, коли вони повністю відокремлені.)
user606723

2
Ваше твердження щодо місця, зайнятого індексами, є дещо оманливим, у некластеризованому індексі дуже мало накладних витрат. Якщо ви можете опублікувати питання з цього приводу, варто вивчити далі. По-друге, я не погоджуюся, що створення індексу - це домен розробника. Це дуже одна з областей, коли співпраця між розробником та DBA може дати найкращі результати.
Марк Сторі-Сміт

1
Я наведу вам приклад однієї з наших таблиць. розмір таблиці: 21052404 Кб. Розмір одного некластеризованого індексу в цій таблиці: 6637470 Кб. Дуже мало накладних? Я думаю, НЕ. Крім того, я не кажу, що з DBA не слід співпрацювати, я кажу, що відповідальність за розробник повинна визначати, чи потрібно створювати новий індекс. Вони не повинні писати SQL і розраховують, що dbas сам зрозуміє це.
user606723

1
Не можна цитувати такі числа без контексту. Без вказівки стовпців індексу NC та кластерного ключа неможливо обчислити частку накладних даних та даних.
Марк Сторі-Сміт

Туш. Ключ - [числовий (24), знак, дата], а стовпці NC - [дата, числовий (24)]. (У цьому конкретному індексі всього дві колонки).
користувач606723

2

Я спробую відповісти лише на перше запитання. Якщо ви можете з початку оцінити навіть приблизно, скільки записів у вас буде за таблицями через певний проміжок часу, ніж я б сказав, що краще почати спочатку розробляти деякі індекси. Спробуйте скористатися деякими тестовими інструментами або тестовими сценаріями, які дозволять автоматизувати якомога більше дзвінків для дзвінків додатків, які, на вашу думку, найчастіше використовуються, і ви побачите, яких сканувань таблиць можна уникнути з самого початку.

Це буде здогадкою на початку, але з часом, коли ви маєте належну статистику використання, ви матимете чіткіше зображення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.