Индексирование только одного значения столбца MySQL

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


person BrainCore    schedule 23.03.2010    source источник
comment
Просто интересно, будет ли проще преобразовать в битовый столбец с именем обработки, где значение будет либо 1, либо 0. Будет использовать меньше места. (Если у вас больше 2 статусов)   -  person Matt MacLean    schedule 23.03.2010
comment
Хорошее предложение. У меня действительно больше двух статусов, но я упростил для простоты.   -  person BrainCore    schedule 23.03.2010
comment
но я упростил для простоты - тогда ладно, если вы не упростили по какой-то другой причине :-)   -  person paxdiablo    schedule 23.03.2010


Ответы (2)


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

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

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

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

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

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

person paxdiablo    schedule 23.03.2010

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

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

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

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

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

if ($member->getStatus() == 'active')
{
}
person Amy B    schedule 23.03.2010
comment
Спасибо за ответ. Строки на самом деле являются ENUM, что означает, что они отображаются на целые числа. Хотя ваше предложение является верным, оно не затрагивает сути моего вопроса: необходимо ли, и если да, то как мне индексировать только определенное значение в столбце? - person BrainCore; 23.03.2010