Який ефект від заміни індексів відфільтрованими (ненульовим значенням) індексами?


10

У нашому проекті працює дуже велика, дуже складна база даних. Отож, близько місяця тому ми помітили, що простір, який використовується індексованими стовпцями, що містять нульові значення, стає надто великим. Як відповідь на це, я написав як скрипт, який динамічно шукатиме всі індекси одного стовпця, що містять більше 1% нульових значень, а потім скидає та відтворює ці індекси у вигляді відфільтрованих індексів за умови, що значення НЕ було NULL. Це знизить і відтворить сотні індексів по всій базі даних і, як правило, звільнить майже 15% місця, що використовується всією БД.

Зараз у мене є два питання з цього приводу:

А) Які недоліки використання фільтрованих індексів таким чином? Я б припускав, що це тільки покращить ефективність роботи, але чи пов'язані якісь ризики щодо ефективності?

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

Дякуємо за будь-яку допомогу!

Редагувати: У відповідь на @Thomas Kejser

Привіт і спасибі, але виявляється, це було катастрофою. У той час ми не розуміли кількох речей, таких як:

  1. Під час запиту SQLOS складає індексні плани, перш ніж визначити, що він не може використовувати значення NULL для приєднання стовпців таблиці. IE, вам справді потрібно мати фільтр пункту WHERE, який відповідає індексу для кожного відфільтрованого індексу, який використовується в запиті, або індекс взагалі не буде використовуватися.
  2. Скасування та створення індексів та надмірне оновлення статистики ще раз після цього все ще може бути недостатньою для створення оновлених планів, які, як ми вважали, вони будуть. Виявляється, що в деяких випадках лише достатньо висока навантаження змусить SQL Server переосмислити плани.
  3. Існує деяка екзотика щодо функціональності планувальника виконання, який важко визначити лише здоровим глуздом та логікою. Із тисячами варіантів різних запитів, що формуються за кодом, навіть, здавалося б, марні покажчики можуть допомогти в деяких статистичних та планових запитах, які в кінцевому підсумку використовуються в критичних запитах.

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


Ви можете також переглянути свою стратегію індексації. Якщо у вас є сотні одиночних індексів поля, мабуть, це не оптимально.
JNK

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

Відповіді:


8

Дуже цікавий підхід. Моя підтримка творчості.

Оскільки ви відвоювали простір, я припускаю, що оригінальні покажчики вже не встановлені? Недоліками відфільтрованих індексів є:

  • Занадто багато з них можуть спричинити надто великий простір пошуку оптимізатора, що призведе до поганих планів запитів у міру вичерпання часу оптимізатора
  • Є кілька ситуацій, коли відфільтрований індекс навіть не буде врахований, навіть якщо нефільтрований еквівалент був би. Зокрема, це може статися, коли ви отримуєте хеш-приєднання в індексованому стовпчику або якщо ви намагаєтесь ЗАМОВИТИ стовпчик (без фільтра)
  • Параметризація запитів не працює з відфільтрованими індексами (див .: http://www.sqlservercentral.com/blogs/practicalsqldba/2013/04/08/sql-server-part-9-filtered-index-a-new-way- для підвищення продуктивності / )

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


"Параметризація запитів не працює з відфільтрованими індексами". це можливо, можливо, виправити за допомогою опції (перекомпіляція)
MichaelD

2

Томас Кейсер відповів на цю тему значно вище.

Я просто думав над тим, щоб додати 2 центи.

Я бачив, що деякі відфільтровані індекси використовуються лише (показані в плані виконання), коли ви точно співпадаєте з пунктом де у вашому запиті, як і де у відфільтрованому індексі.

ви намагалися використовувати індексовані види ? розріджені стовпці ?

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

Місця може бути більше, ніж один. Але так само, як і в некластерних індексах, занадто багато сповільнить ваше записування.

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

Однак, як я розумію, ваша головна стурбованість, the null valuesтому я б запропонував вам ЗАПИСНІ стовпці у своїх індексах .

Рідкі стовпчики особливо підходять для відфільтрованих індексів

Оскільки я рекламував розріджені стовпці, я б не почував себе добре, якби я також не розповів вам про його обмеження:

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

Внаслідок цього

додаткова вимога до пам'яті, оновлення можуть несподівано вийти з помилки 576, коли загальний розмір рядка, включаючи цю накладну пам'ять, перевищує 8019,

і жодні стовпці не можуть бути витіснені з рядка.

Розглянемо> приклад таблиці, що містить 600 розріджених стовпців типу bigint.

Якщо є 571 ненульових стовпців, то загальний розмір на диску становить 571 * 12 = 6852 байт. Після включення додаткових накладних рядків та розрізненого заголовка стовпця це збільшується до приблизно 6895 байт. Сторінка все ще містить близько 1124 байтів, доступних на диску. Це може створити враження, що додаткові стовпці можна успішно оновити. Однак під час оновлення в пам'яті є додаткові накладні витрати, що дорівнює 2 * (кількість ненульових розріджених стовпців). У цьому прикладі, включаючи додаткову накладну - 2 * 571 = 1142 байти - збільшується розмір рядка на диску приблизно до 8037 байт. Цей розмір перевищує максимально дозволений розмір 8019 байт. Оскільки всі стовпці мають типи даних фіксованої довжини, їх не можна відсунути з рядка. В результаті оновлення не вдається з помилкою 576.

Більше подробиць за посиланням вище, проте я вважаю за краще тут також це попередження:

Для зміни стовпця з розрідженого на нерозбірливий або нерозбірливий на розріджений потрібно змінити формат зберігання стовпця.

Система баз даних SQL Server використовує наступну процедуру для здійснення цієї зміни:

1 - додає новий стовпець до таблиці у новому розмірі та форматі зберігання.

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

3 - Видаляє стару колонку зі схеми таблиці.

4 - Перебудовує таблицю (якщо немає кластерного індексу) або перебудовує кластерний індекс, щоб повернути простір, використаний у старому стовпчику.


1
Привіт. Трохи запізнюючись на перемогу, але так, поки ми давно відмовились від підходу, описаного в цій темі, недавно ми повернулися до нього з більш вибірковим підходом. В основному ми розглядали використання статистики та бізнес-модель для підтвердження індексів на таблиці за таблицею. Потім перевірив його, додавши новий відфільтрований індекс на стороні від звичайного та перевірив, чи не за кілька тижнів перевіряється, який з них в кінцевому підсумку використовується. Після підтвердження того, що ТОЛЬКО відфільтровані індекси використовувались у нових планах, ми скинули звичайні нефільтровані.
Кан

1
Крім того, ми змінили досить багато стовпців на рідкісні типи. Проблема з цим, однак, полягає в тому, що, як ви бачите з MSDN, зміна типу стовпця на розрізнене в основному змушує відтворити весь кластерний індекс. Це робить досить важким для великих складних столів. Тож ми перейменували обмеження та таблицю, створили нову з тією ж моделлю та оригінальною назвою, але із розрідженими стовпцями, а потім перенесли дані у нову таблицю у відповідних партіях. Потім одного разу перевірив, що все в порядку, і всі індекси та FK знову на місці, скинув старі таблиці.
Кан

1
Крім того, в деяких випадках використання стиснення сторінок було набагато кращим, тому ми натомість зробили це замість цього. Це також зручно, оскільки ви можете просто створити наявний кластерний індекс за допомогою DROP_EXISTING = ON, щоб зробити його далеко, набагато швидшим, ніж пройти рідкий маршрут. Тим більше, що це дозволяє уникнути суттєвих клопотів щодо повторного управління індексами та FK.
Кан
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.