Перше, що ви повинні знати, це те, що індекси - це спосіб уникнути сканування повної таблиці, щоб отримати результат, який ви шукаєте.
Існують різні типи індексів і вони реалізовані в шарі зберігання, тому між ними немає стандарту, і вони також залежать від двигуна пам’яті, який ви використовуєте.
InnoDB та індекс дерева B +
Для InnoDB найпоширенішим типом індексу є індекс на основі дерева B +, який зберігає елементи в упорядкованому порядку. Крім того, вам не доведеться отримувати доступ до реальної таблиці, щоб отримати індексовані значення, що робить ваш шлях повернення запиту швидшим.
"Проблема" щодо цього типу індексу полягає в тому, що вам потрібно запитати про найменше значення, щоб використовувати індекс. Отже, якщо ваш індекс має два стовпці, скажіть прізвище та ім'я, ім'я, порядок, який ви запитуєте в цих полях, має велике значення .
Отже, враховуючи наступну таблицю:
CREATE TABLE person (
last_name VARCHAR(50) NOT NULL,
first_name VARCHAR(50) NOT NULL,
INDEX (last_name, first_name)
);
Цей запит скористається індексом:
SELECT last_name, first_name FROM person
WHERE last_name = "John" AND first_name LIKE "J%"
Але наступного не буде
SELECT last_name, first_name FROM person WHERE first_name = "Constantine"
Тому що ви first_name
спочатку запитуєте стовпець, і це не найменший стовпець у індексі.
Цей останній приклад ще гірший:
SELECT last_name, first_name FROM person WHERE first_name LIKE "%Constantine"
Тому що зараз ви порівнюєте найправішу частину самого правого поля в індексі.
Хеш-індекс
Це інший тип індексу, який, на жаль, підтримує лише бекенд пам'яті. Це блискавки швидко , але корисно тільки для повних пошуків, а це значить , що ви не можете використовувати його для таких операцій , як >
, <
або LIKE
.
Оскільки він працює лише для бекенда пам'яті, ви, ймовірно, не будете використовувати його дуже часто. Основний випадок, про який я зараз думаю, - це те, що ви створюєте тимчасову таблицю в пам'яті з набором результатів з іншого вибору та виконуєте безліч інших виділень у цій тимчасовій таблиці за допомогою хеш-індексів.
Якщо у вас є велике VARCHAR
поле, ви можете "емулювати" використання хеш-індексу при використанні B-дерева, створивши інший стовпець і збереживши на ньому хеш великого значення. Скажімо, ви зберігаєте URL-адресу в полі, і значення досить великі. Ви також можете створити ціле поле, яке називається, url_hash
і використовувати хеш-функцію, як CRC32
або будь-яку іншу хеш-функцію, для хешування URL-адреси при його вставці. І тоді, коли вам потрібно буде запитувати це значення, ви можете зробити щось подібне:
SELECT url FROM url_table WHERE url_hash=CRC32("http://gnu.org");
Проблема з наведеним вище прикладом полягає в тому, що оскільки CRC32
функція генерує досить невеликий хеш, у вас вийде багато зіткнень у хешованих значеннях. Якщо вам потрібні точні значення, ви можете усунути цю проблему, виконавши наступне:
SELECT url FROM url_table
WHERE url_hash=CRC32("http://gnu.org") AND url="http://gnu.org";
Все ще варто зафіксувати речі, навіть якщо число зіткнення є великим, тому що ви будете виконувати лише друге порівняння (рядкове) з повторними хешами.
На жаль, використовуючи цю техніку, вам все одно потрібно вдарити по таблиці, щоб порівняти url
поле.
Загорнути
Деякі факти, які ви можете враховувати кожного разу, коли хочете поговорити про оптимізацію:
Порівняння цілих чисел набагато швидше порівняння з рядками. Це можна проілюструвати на прикладі про емуляцію хеш-індексу в InnoDB
.
Можливо, додавання додаткових кроків у процесі робить це швидше, а не повільніше. Це можна проілюструвати тим, що ви можете оптимізувати a SELECT
, розділивши його на два етапи, зробивши перший, зберігати значення в новоствореній таблиці пам'яті, а потім виконати більш важкі запити в цій другій таблиці.
У MySQL є й інші індекси, але я думаю, що B + Tree - це найчастіше використовуване, а хеш - це добре знати, але інші ви можете знайти в документації на MySQL .
Я настійно рекомендую прочитати книгу "Високопродуктивний MySQL", відповідь вище, безумовно, ґрунтувалася на її главі про індекси.