Индексирование только одного значения столбца MySQL - PullRequest
2 голосов
/ 23 марта 2010

У меня есть MySQL InnoDB таблица со столбцом состояния. Статус может быть «выполнено» или «обрабатывается». По мере роста таблицы не более 0,1% значений состояния будут «обрабатываться», тогда как остальные 99,9% значений будут «выполнены». Это кажется хорошим кандидатом на индекс из-за высокой селективности для «обработки» (хотя и не для «выполнено»). Можно ли создать индекс для столбца состояния, который индексирует только значение «обработка»? Я не хочу, чтобы индекс тратил огромное количество пространства, индексируя «готово».

Ответы [ 2 ]

3 голосов
/ 23 марта 2010

Я не знаю ни одного стандартного способа сделать это, но мы решили подобную проблему раньше, используя две таблицы, Processing и Done в вашем случае, первая с индексом, вторая без.

Предполагая, что строки никогда не переключаются обратно с done на processing, вот шаги, которые вы можете использовать:

  1. Когда вы создаете запись, вставьте ее в таблицу Processing со столбцом, установленным в processing.
  2. По окончании установите для столбца значение done.
  3. Периодически сканируйте таблицу Processing, перемещая строки done в таблицу Done.

Последний может быть хитрым. Вы можете сделать вставку / удаление в транзакции, чтобы убедиться, что она переносится правильно, или вы можете использовать уникальный идентификатор, чтобы обнаружить, если он уже передан, а затем просто удалить его из Processing (у меня нет опыта поддержки транзакций MySQL, поэтому тоже даю такую ​​опцию).

Таким образом, вы индексируете только несколько из 99,9% строк done, которые еще не были перенесены в таблицу Done. Он также будет работать с несколькими состояниями processing, как вы упомянули в комментариях (записи переносятся только тогда, когда они достигают состояния done, все остальные состояния остаются в таблице Processing).

Это похоже на перенос исторических данных (которые больше никогда не изменятся) для эффективности в отдельную таблицу. Это может усложнить некоторые запросы, когда вам нужен доступ как к done, так и к не done строкам, так как вам нужно объединить две таблицы, поэтому помните, что есть компромисс.

0 голосов
/ 23 марта 2010

Лучшее решение: не используйте строки для обозначения статусов.Вместо этого используйте константы в вашем коде с описательными именами => целочисленными значениями.Затем это целое число сохраняется в базе данных, и MySQL будет работать намного быстрее, чем со строками.

Я не знаю, какой язык вы используете, но, например, в PHP:

class Member
{
   const STATUS_ACTIVE = 1;
   const STATUS_BANNED = 2;
}

if ($member->getStatus() == Member::STATUS_ACTIVE)
{
}

вместо того, что у вас сейчас:

if ($member->getStatus() == 'active')
{
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...