Які стовпці зазвичай дають хороші індекси?


98

Як продовження " Що таке індекси та як я можу використовувати їх для оптимізації запитів у моїй базі даних? ", Де я намагаюся дізнатись про індекси, які стовпці є хорошими кандидатами на індекси? Конкретно для бази даних MS SQL?

Після деякого гуглювання все, що я прочитав, свідчить про те, що стовпці, які, як правило, збільшуються та унікальні, роблять хороший індекс (такі речі, як auto_increment MySQL), я це розумію, але я використовую MS SQL і використовую GUID для первинних ключів, так що здається щоб індекси не приносили користі стовпцям GUID ...


Як щодо "кулінарної книги": mysql.rjweb.org/doc.php/index_cookbook_mysql
Рік Джеймс,

Відповіді:


110

Індекси можуть зіграти важливу роль в оптимізації запитів та швидкому пошуку результатів з таблиць. Отже, найважливішим кроком є ​​вибір стовпців для індексації. Існує два основних місця, де ми можемо розглянути індексацію: стовпці, на які посилається речення WHERE, і стовпці, що використовуються в реченнях JOIN. Коротше кажучи, такі стовпці мають бути проіндексовано, за якими вам потрібно здійснити пошук певних записів. Припустимо, у нас є таблиця з іменами покупці, де запит SELECT використовує індекси, як показано нижче:

SELECT
 buyer_id /* no need to index */
FROM buyers
WHERE first_name='Tariq' /* consider to use index */
AND last_name='Iqbal'   /* consider to use index */

Оскільки на посилання "customer_id" посилається в частині SELECT, MySQL не використовуватиме його для обмеження вибраних рядків. Отже, немає великої потреби його індексувати. Нижче наведено ще один приклад, який мало відрізняється від наведеного:

SELECT
 buyers.buyer_id, /* no need to index */
 country.name    /* no need to index */
FROM buyers LEFT JOIN country
ON buyers.country_id=country.country_id /* consider to use index */
WHERE
 first_name='Tariq' /* consider to use index */
AND
 last_name='Iqbal' /* consider to use index */

Згідно з вищезазначеними запитами first_name, стовпці last_name можна індексувати, оскільки вони знаходяться в реченні WHERE. Крім того, додаткове поле, country_id із таблиці country, може бути розглянуто для індексації, оскільки воно знаходиться в реченні JOIN. Отже, індексацію можна розглядати в кожному полі речення WHERE або речення JOIN.

У наведеному нижче списку також пропонується кілька порад, про які слід завжди пам’ятати, коли маєте намір створювати індекси у своїх таблицях:

  • Індексуйте лише ті стовпці, які потрібні в реченнях WHERE та ORDER BY. Індексування ряду стовпців призведе до деяких недоліків.
  • Спробуйте скористатися функцією "префікс індексу" або "індекс багатостолбців" MySQL. Якщо ви створюєте індекс, такий як INDEX (ім'я, прізвище), не створюйте INDEX (ім'я). Однак "префікс індексу" або "індекс із кількома стовпцями" не рекомендується застосовувати у всіх випадках пошуку.
  • Використовуйте атрибут NOT NULL для тих стовпців, у яких ви розглядаєте індексацію, щоб значення NULL ніколи не зберігалися.
  • Використовуйте параметр --log-long-format для реєстрації запитів, які не використовують індекси. Таким чином, ви можете перевірити цей файл журналу та відповідно налаштувати свої запити.
  • Оператор EXPLAIN допомагає виявити, як MySQL буде виконувати запит. Він показує, як і в якому порядку об’єднуються таблиці. Це може бути дуже корисним для визначення способу написання оптимізованих запитів та необхідності індексації стовпців.

Оновлення (23 лютого 2015 р.):

Будь-який індекс (хороший / поганий) збільшує час вставки та оновлення.

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

Напевно, в будь-якій книзі "Індексна сторінка" може мати початкову сторінку глави, починається номер сторінки теми, а також починається сторінка підтеми. Деякі роз’яснення на сторінці «Індекс» допомагають, але більш детальний покажчик може вас спантеличити або злякати. Індекси також мають пам’ять.

Вибір індексу повинен бути розумним. Майте на увазі, не для всіх стовпців потрібен індекс.


Спасибі Сомнату, отже, це означає, що індекси слід створювати лише для стовпців, де ми плануємо використовувати WHERE, JOINSчи HAVING?
Мухаммед Бабар

3
Так, використовуйте індекси для стовпців, де ви плануєте використовувати WHERE, JOINS або HAVING. Але також майте на увазі, що всі стовпці умов не вимагають індексів. Іноді, коли стовпець умови використовується лише один раз, тому йому може не знадобитися індекс, тоді як інший стовпець умови використовується у багатьох запитах, тому волійте більше для індексації в цьому стовпці.
Somnath Muluk

1
Відповіді було б корисно, якщо в розділі TL; DR буде вказано "стовпці, на які посилається речення WHERE, і стовпці, що використовуються в реченнях JOIN".
jpmc26,

Отже, ви говорите, що якщо у своєму WHEREреченні я перевіряю значення поля, де його стовпець може приймати лише два значення, то я повинен індексувати цей двійковий стовпець? Це здається неправильним.
AjaxLeung

@AjaxLeung: Пам'ятайте сентенцію Кнута "Передчасна оптимізація - корінь усього зла". Ви можете зробити індекс на двійкових стовпцях, але це повинно залежати від того, якою вартістю (як вставка, час оновлення). Якщо ваша бізнес-логіка часто залежить від цього двійкового комутатора, тоді двійковий стовпець може мати індекс.
Somnath Muluk

20

Деякі люди відповіли на подібне запитання тут: Звідки ви знаєте, що таке хороший показник?

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

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

Удачі!


9

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

Індекси будуть корисні, якщо:

  • Колона або колони мають високий ступінь унікальності
  • Часто потрібно шукати певне значення або діапазон значень для стовпця.

Вони не будуть корисні, якщо:

  • Ви вибираєте великий% (> 10-20%) рядків у таблиці
  • Проблема з додатковим використанням простору
  • Ви хочете максимізувати продуктивність вставки. Кожен індекс таблиці знижує продуктивність вставки та оновлення, оскільки їх потрібно оновлювати щоразу, коли змінюються дані.

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


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

5

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

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

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

(Вибачаюся, якщо я повторюю речі, згадані в іншому вашому запитанні, я раніше з ними не стикався.)


5

Будь-який стовпець, який буде регулярно використовуватися для отримання даних із таблиці, повинен бути проіндексований.

Сюди входять: зовнішні ключі -

select * from tblOrder where status_id=:v_outstanding

описові поля -

select * from tblCust where Surname like "O'Brian%"

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

select * from tblOrder where paidYN='N'

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

3

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

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


3

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

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

Також можна створити "кластерний індекс", який фізично змінить порядок даних. Однак ви можете мати лише одне з них для таблиці, тоді як ви можете мати кілька некластеризованих індексів.


Ну, це не зовсім точно. Ви можете легко створити звичайний некластерний індекс у стовпці GUID - чому ні? GUID має великий недолік, якщо ви використовуєте його в якості кластеризаційного ключа (наприклад, для КЛАСТЕРОВАНОГО ІНДЕКСУ) - тоді використовувати його буде катастрофою.
marc_s

1

Основним правилом були стовпці, які часто використовуються в реченнях WHERE, ORDER BY та GROUP BY, або будь-які, які, здавалося, часто використовуються в об'єднаннях. Майте на увазі, я маю на увазі індекси, а НЕ первинний ключ

Не дати "ванільно-іш" відповіді, але це справді залежить від того, як ви отримуєте доступ до даних


1

Первинним ключем завжди повинен бути індекс. (Я б здивований, якби насправді це не було проіндексовано MS SQL.) Ви також повинні індексувати стовпці самі SELECTабо ORDERчасто; їх метою є як швидке пошук одного значення, так і швидше сортування.

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


1

Цифрові типи даних, які впорядковані за зростанням чи спаданням, є хорошими індексами з багатьох причин. По-перше, числа, як правило, швидше оцінюються, ніж рядки (varchar, char, nvarchar тощо). По-друге, якщо ваші значення не впорядковані, можливо, потрібно буде перемішати рядки та / або сторінки, щоб оновити індекс. Це додаткові накладні витрати.

Якщо ви використовуєте SQL Server 2005 і налаштували на використання унікальних ідентифікаторів (посібників), і НЕ потрібно, щоб вони мали випадковий характер, перевірте послідовний тип унікального ідентифікатора.

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


0

Якщо ви використовуєте GUID, це має бути ще швидше. Припустимо, у вас є записи

  1. 100
  2. 200
  3. 3000
  4. ….

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


0

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

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

Спочатку слід з’ясувати, які дані ви будете запитувати, а потім визначитесь, які дані вам потрібно проіндексувати.

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