#mysql #optimization #indexing
#mysql #оптимизация #индексирование
Вопрос:
Вот моя таблица:
CREATE TABLE `letters` (
`a` bigint(20) unsigned NOT NULL,
`b` bigint(20) unsigned NOT NULL,
`c` bigint(20) unsigned NOT NULL,
`d` bigint(20) unsigned NOT NULL,
`e` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8$$
- В таблице будет около 1 миллиарда строк.
- Можно запрашивать каждый столбец; на каждый столбец можно ссылаться. например:
- ВЫБЕРИТЕ [любой столбец] ИЗ букв, ГДЕ [любой / любой другой столбец] В ([подзапрос или список]);
Мой вопрос: какие индексы я должен добавить, чтобы ускорить любой запрос в приведенном выше формате? (Также, если возможно, пожалуйста, попробуйте описать, «почему» это / они должны быть добавлены, чтобы я мог извлечь уроки из вашего ответа).
Спасибо!
— Дополнительная информация: вставки будут происходить довольно регулярно (несколько / несколько раз в секунду), но запросы select будут выполняться чаще.
Комментарии:
1. Вы действительно не предоставили ничего, что можно было бы продолжить, не уточнив ваши общие запросы.
2. Вместо того, чтобы перечислять каждую возможность запроса, я предоставил шаблон всех запросов. Предположим, что каждый столбец может входить в каждый пробел. Вот почему я задаю вопрос, это не просто: используйте этот индекс, потому что ваши запросы склоняются к нему. — Нет «общих запросов». Это равномерное распределение указанного шаблона.
3. Вы могли бы разделить таблицу по столбцу ‘e’, а затем настроить индексы для b-d
4. Не имеет значения. ГДЕ e = 1 — это избирательность, а не распределение значений e по другим перестановкам столбцов. Если вы сделали, ГДЕ a = 42 и e = 1, тогда да, это имеет значение.
5. Если бы запрос не включал предикат на ‘e’, тогда, да, скорее всего, были бы некоторые дополнительные накладные расходы при объединении результатов из нескольких разделов. В идеале разбиение (и ничто не мешает вам разбивать разделы на любые другие столбцы, кстати) должно основываться на наиболее часто используемом столбце предикатов (где a =, где b =, где c = и т. Д. И т. Д.). Еще одна вещь, на которую вы могли бы обратить внимание, — действительно ли вам нужны все данные. Можно ли что-нибудь из этого заархивировать, чтобы уменьшить объемы данных и, следовательно, ускорить выполнение любых запросов? Удачи вам!
Ответ №1:
Поскольку в предложении WHERE может появиться любой столбец, вы должны добавить индекс для каждого столбца, за исключением поля a, поскольку оно уже является ПЕРВИЧНЫМ КЛЮЧОМ и, как таковое, уже проиндексировано.
ОБНОВЛЕНИЕ: что касается последующего обсуждения, Poodlehat указал, что столбец e имеет низкую избирательность индекса, т. Е. «Отношение количества различных значений в индексированном столбце / столбцах к количеству записей в таблице». По этой причине неясно, поможет ли добавление индекса в столбец e или замедлит запросы. Итак, Лукас попробует экспериментально и, надеюсь, поделится с нами результатами.
Комментарии:
1. Это то, что, по моему мнению, следует сделать, но будет ли иметь один индекс в каждом столбце намного быстрее, чем отсутствие индексов (кроме PK)? Я знаю, что мне не следует добавлять составные индексы для каждой пары 2, потому что тогда мои вставки будут длиться вечно.
2. Плохая идея добавлять индекс к столбцам с плохой избирательностью.
3. Вы правы, но, предполагая, что 15 значений столбца e распределены равномерно, это означает 6,66% — В этом документе об Oracle , но это общее руководство, говорится: мы должны создавать индексы для таблиц, которые часто запрашиваются для менее чем 15% строк таблицы.
4. @stivlo — К сожалению, вы не можете предположить равномерное распределение. Вероятно, будут случаи, когда одно значение ‘e’ приведет к 20% результатов, еще 15%, еще 10%, а остальные .. меньше%.
5. @Lucas, да, возможно, поэтому, возможно, он мог бы попробовать с индексом в столбце e и без него и посмотреть, что работает быстрее.
Ответ №2:
Я думаю, вам нужно иметь уникальный индекс a
(или это должен быть первичный ключ), определенно индексы b,c,d
(для каждого). Нет необходимости в индексации e
(он все равно не будет использоваться, поскольку, как вы говорите, он имеет всего 15 разных значений)