Коллега попросил меня объяснить, как индексы (индексы?) Повышают производительность; Я пытался это сделать, но запутался.
Я использовал модель ниже для объяснения (база данных ошибок / диагностики). Он состоит из трех таблиц:
- Список бизнес-систем, таблица «Система», содержащая их названия
- Список различных типов трассировок, таблица «TraceTypes», определяющая, какие виды сообщений об ошибках могут регистрироваться
- Актуальные сообщения трассировки с внешними ключами из таблиц
System
и TraceTypes
Я использовал MySQL для демонстрации, однако я не помню типы таблиц, которые я использовал. Я думаю, что это был InnoDB.
System TraceTypes
----------------------------- ------------------------------------------
| ID | Name | | ID | Code | Description |
----------------------------- ------------------------------------------
| 1 | billing | | 1 | Info | Informational mesage |
| 2 | hr | | 2 | Warning| Warning only |
----------------------------- | 3 | Error | Failure |
| ------------------------------------------
| ------------|
Traces | |
--------------------------------------------------
| ID | System_ID | TraceTypes_ID | Message |
--------------------------------------------------
| 1 | 1 | 1 | Job starting |
| 2 | 1 | 3 | System.nullr..|
--------------------------------------------------
Сначала я добавил несколько записей во все таблицы и продемонстрировал, что приведенный ниже запрос выполняется за 0,005 секунды:
select count(*) from Traces
inner join System on Traces.System_ID = System.ID
inner join TraceTypes on Traces.TraceTypes_ID = TraceTypes.ID
where
System.Name='billing' and TraceTypes.Code = 'Info'
Затем я сгенерировал больше данных (пока нет индексов)
- «Система» содержит около 100 записей
- "TraceTypes" содержит около 50 записей
- «Следы» содержали ~ 10 миллионов записей.
Теперь предыдущий запрос занял 8-10 секунд.
Я создал индексы для столбца Traces.System_ID
и столбца Traces.TraceTypes_ID
. Теперь этот запрос выполняется за миллисекунды:
select count(*) from Traces where System_id=1 and TraceTypes_ID=1;
Это было также быстро:
select count(*) from Traces
inner join System on Traces.System_ID = System.ID
where System.Name='billing' and TraceTypes_ID=1;
, но предыдущий запрос, объединяющий все три таблицы, все еще занимал 8-10 секунд.
Только при создании составного индекса (столбцы System_ID и TraceTypes_ID включены в индекс) скорость снижалась до миллисекунд.
Основное утверждение, которому меня учили ранее, это «все столбцы, которые вы используете для объединения, должны быть проиндексированы».
Однако в моем сценарии у меня были индексы как System_ID
, так и TraceTypes_ID
, однако MySQL их не использовал. Вопрос - почему? Мои ставки - соотношение количества предметов 100: 10 000 000: 50 делает индексы из одного столбца слишком большими для использования. Но так ли это?