У меня есть таблица MySQL InnoDB со столбцом состояния. Статус может быть «готово» или «в обработке». По мере роста таблицы не более 0,1 % значений статуса будут «обрабатываться», тогда как остальные 99,9 % значений будут «выполнены». Это кажется отличным кандидатом для индекса из-за высокой избирательности для «обработки» (но не для «готово»). Можно ли создать индекс для столбца состояния, который индексирует только значение «обработка»? Я не хочу, чтобы индекс тратил впустую огромное количество места на индексацию «сделано».
Индексирование только одного значения столбца MySQL
Ответы (2)
Я не знаю какого-либо стандартного способа сделать это, но мы уже решали аналогичную проблему, используя две таблицы, Processing
и Done
в вашем случае, первая с индексом, вторая без.
Предполагая, что строки никогда не переключаются обратно с done
на processing
, вот шаги, которые вы можете использовать:
- Когда вы создаете запись, вставьте ее в таблицу
Processing
со столбцом, установленным наprocessing
. - Когда все будет готово, установите для столбца значение
done
. - Периодически очищайте таблицу
Processing
, перемещаяdone
строк в таблицуDone
.
С последним может быть сложно. Вы можете выполнить вставку/удаление в транзакции, чтобы обеспечить ее правильную передачу, или вы можете использовать уникальный идентификатор, чтобы определить, была ли она уже передана, а затем просто удалить ее из Processing
(у меня нет опыта работы с поддержкой транзакций MySQL, поэтому я также дает этот вариант).
Таким образом, вы индексируете только несколько из 99,9% done
строк, которые еще не были перенесены в таблицу Done
. Он также будет работать с несколькими состояниями processing
, как вы упомянули в комментариях (записи передаются только тогда, когда они достигают состояния done
, все остальные состояния остаются в таблице Processing
).
Это похоже на перенос исторических данных (вещей, которые больше никогда не изменятся) в отдельную таблицу для повышения эффективности. Это может усложнить некоторые запросы, когда вам нужен доступ как к done
, так и к не done
строкам, поскольку вам нужно соединить две таблицы, поэтому имейте в виду, что есть компромисс.
Лучшее решение: не используйте строки для обозначения статусов. Вместо этого используйте в коде константы с описательными именами => целочисленные значения. Затем это целое число сохраняется в базе данных, и MySQL будет работать НАМНОГО быстрее, чем со строками.
Я не знаю, какой язык вы используете, но, например, в PHP:
class Member
{
const STATUS_ACTIVE = 1;
const STATUS_BANNED = 2;
}
if ($member->getStatus() == Member::STATUS_ACTIVE)
{
}
вместо того, что у вас есть сейчас:
if ($member->getStatus() == 'active')
{
}