Для чого це потрібно?
Коли дані зберігаються на дискових пристроях зберігання даних, вони зберігаються у вигляді блоків даних. До цих блоків звертаються в повному обсязі, що робить їх атомним диском доступу. Дискові блоки структуровані приблизно так само, як і пов'язані списки; обидва містять розділ для даних, вказівник на розташування наступного вузла (або блоку), і обидва не повинні зберігатися безперервно.
Через те, що ряд записів можна сортувати лише за одним полем, ми можемо констатувати, що для пошуку в полі, яке не сортується, потрібен лінійний пошук, який вимагає N/2
доступу до блоку (в середньому), де N
кількість блоків, які стіл охоплюється. Якщо це поле - це не ключове поле (тобто не містить унікальних записів), тоді слід шукати всю область таблицьN
доступ до блоку.
Тоді як із відсортованим полем може використовуватися двійковий пошук, який має log2 N
блок доступу. Оскільки дані відсортовані за не-ключовим полем, решту таблиці не потрібно шукати за дублюючими значеннями, як тільки буде знайдено більш високе значення. Таким чином, підвищення продуктивності є значним.
Що таке індексація?
Індексація - це спосіб сортування декількох записів за кількома полями. Створення індексу на полі в таблиці створює іншу структуру даних, яка містить значення поля та вказівник на запис, до якого він відноситься. Ця структура індексу потім сортується, що дозволяє виконувати Binary Searches на ній.
Недоліком індексації є те, що ці індекси потребують додаткового місця на диску, оскільки індекси зберігаються разом у таблиці за допомогою двигуна MyISAM, цей файл може швидко досягти обмежень розмірів базової файлової системи, якщо багато полів в одній таблиці індексуються .
Як це працює?
По-перше, накреслимо зразкову схему таблиці баз даних;
Назва поля Тип даних Розмір на диску
id (Первинний ключ) Непідписаний INT 4 байти
firstName Char (50) 50 байт
lastName Char (50) 50 байт
emailAddress Char (100) 100 байт
Примітка : замість варшара було використано char, щоб забезпечити точний розмір на значенні диска. Ця зразкова база даних містить п'ять мільйонів рядків і є нерозробленою. Тепер буде проаналізовано виконання декількох запитів. Це запит із використанням ідентифікатора (відсортоване ключове поле) та запиту, що використовує firstName (не-ключове несортоване поле).
Приклад 1 - відсортовано проти несортованих полів
Враховуючи нашу зразкову базу даних r = 5,000,000
записів фіксованого розміру, що дає довжину R = 204
байтів, і вони зберігаються в таблиці за допомогою двигуна MyISAM, який використовує типовий розмір B = 1,024
байтів блоків . Коефіцієнтом блокування таблиці будуть bfr = (B/R) = 1024/204 = 5
записи на блок диска. Загальна кількість блоків, необхідних для утримання таблиці, - це N = (r/bfr) = 5000000/5 = 1,000,000
блоки.
Лінійний пошук у полі id вимагає середнього N/2 = 500,000
доступу до блоку, щоб знайти значення, враховуючи, що поле id - це ключове поле. Але оскільки поле id також упорядковане, може бути проведений двійковий пошук, що вимагає середнього log2 1000000 = 19.93 = 20
доступу до блоку. Миттєво ми можемо побачити, що це різке поліпшення.
Тепер поле firstName не є ні відсортованим, ні ключовим полем, тому двійковий пошук неможливий, а також значення не є унікальними, і, таким чином, таблиця вимагатиме пошуку до кінця для точного N = 1,000,000
доступу до блоку. Саме цю ситуацію індексація має на меті виправити.
Зважаючи на те, що запис в індексі містить лише індексоване поле та вказівник на початковий запис, можна вважати, що він буде меншим, ніж запит з багатопольового поля, на який він вказує. Таким чином, сам індекс вимагає меншої кількості дискових блоків, ніж оригінальна таблиця, яка, отже, вимагає меншої кількості доступу до блоку, щоб перебрати через. Схема індексу в полі firstName наведена нижче;
Назва поля Тип даних Розмір на диску
firstName Char (50) 50 байт
(покажчик запису) Спеціальні 4 байти
Примітка . Покажчики в MySQL мають довжину 2, 3, 4 або 5 байт залежно від розміру таблиці.
Приклад 2 - індексація
Враховуючи нашу зразкову базу даних r = 5,000,000
записів із індексною довжиною R = 54
байтів та використанням байтів за розміром блоків за замовчуванням B = 1,024
. Коефіцієнтом блокування індексу будуть bfr = (B/R) = 1024/54 = 18
записи на блок диска. Загальна кількість блоків, необхідних для утримання індексу, - це N = (r/bfr) = 5000000/18 = 277,778
блоки.
Тепер пошук за допомогою поля firstName може використовувати індекс для підвищення продуктивності. Це дозволяє здійснювати двійковий пошук індексу із середнім рівнем log2 277778 = 18.08 = 19
доступу до блоків. Щоб знайти адресу фактичного запису, який потребує подальшого доступу до блоку для зчитування, приведення загального до 19 + 1 = 20
блокового доступу, далекий від 1 000 000 доступу до блоку, необхідного для пошуку відповідності firstName у неіндексованій таблиці.
Коли його слід використовувати?
Зважаючи на те, що для створення індексу необхідний додатковий простір на диску (277,778 блоків додатково з вищевказаного прикладу, збільшення на 28%), і що занадто багато індексів можуть спричинити проблеми, що виникають із-за обмежень розміру файлових систем, слід обережно продумати правильний вибір поля для індексації.
Оскільки індекси використовуються лише для прискорення пошуку відповідного поля в записах, очевидно, що поля індексації, які використовуються лише для виводу, будуть просто марною витратою дискового простору та часу обробки при виконанні операції вставки або видалення, і таким чином слід уникати. З огляду на характер двійкового пошуку, важливість є унікальністю або унікальністю даних. Індексація на полі з кардинальністю 2 розділить дані навпіл, тоді як кардинальність 1000 поверне приблизно 1000 записів. При такій низькій кардинальності ефективність зводиться до лінійного сортування, і оптимізатор запитів уникне використання індексу, якщо кардинальність становить менше 30% від рекордної кількості, що фактично робить індекс марною витратою місця.