Тип MySQL ENUM против таблиц соединения

Мое требование

Таблица должна поддерживать столбец состояния.

Этот столбец представляет одно из 5 состояний.


первоначальный дизайн

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

  • 0 = начало
  • 1 = работает
  • 2 = разбился
  • 3 = приостановлено
  • 4 = остановлено

Поскольку я не хочу, чтобы мое приложение поддерживало сопоставление целых чисел с их описанием строк, я планирую поместить их в отдельную таблицу описания состояний (полагаясь на отношение FK).

Затем я обнаружил, что MySQL имеет тип ENUM, который точно соответствует моим требованиям. Кроме прямой зависимости от MySQL, есть ли подводные камни при использовании типа ENUM?

5 ответов

Решение
  • Изменение набора значений в ENUM требует ALTER TABLE которая может вызвать реструктуризацию таблицы - невероятно дорогая операция (реструктуризация таблицы не произойдет, если вы просто добавите одно новое значение в конец определения ENUM, но если вы удалите одно или измените порядок, она выполнит таблицу реструктурировать). Принимая во внимание, что изменение набора значений в таблице поиска так же просто, как INSERT или DELETE.

  • Невозможно связать другие атрибуты со значениями в ENUM, например, какие из них удалены, а какие можно добавить в раскрывающийся список в вашем пользовательском интерфейсе. Однако таблица поиска может включать дополнительные столбцы для таких атрибутов.

  • Очень сложно запросить ENUM, чтобы получить список различных значений, в основном требуя, чтобы вы запросили определение типа данных из INFORMATION_SCHEMAи разбор списка из BLOB вернулся. Вы могли бы попробовать SELECT DISTINCT status из вашей таблицы, но он получает только те значения состояния, которые используются в данный момент, что может быть не всеми значениями в ENUM. Однако, если вы храните значения в справочной таблице, их легко запрашивать, сортировать и т. Д.

Я не большой поклонник ENUM, как вы можете сказать.:-)

То же самое относится к ограничениям CHECK, которые просто сравнивают столбец с фиксированным набором значений. Хотя MySQL в любом случае не поддерживает ограничения CHECK.

Вот статья о скоростном сравнении enum. Может быть, это дает некоторые подсказки. ИМХО, это должно быть ограничено использованием в фиксированном списке строк ("Да / Нет", "Ребенок / Взрослый"), которое с вероятностью 99% не изменится в будущем.

Перечисления в mysql плохи по уже объясненным причинам.
Я могу добавить следующий факт: Enum не обеспечивает никакой проверки на стороне сервера. Если вы вставите строку со значением, которое не завершается в определении enum, вы получите хорошее или NULL-значение в БД, в зависимости от NULL-способности объявления поля enum.

Моя точка зрения о крошечных:
- перечисления ограничены 65535 значениями
- если вам не нужно больше 256 значений, tinyint будет занимать меньше места для каждой строки, и его поведение будет гораздо более "предсказуемым".

Если у вас много данных в вашей БД (больше данных, чем у вас ОЗУ) и значения ENUM НИКОГДА не изменятся, я бы использовал ENUM, а не соединение. Это должно быть быстрее.
Подумайте об этом, в случае объединения вам нужен индекс по внешнему ключу и индекс по первичному ключу в другой таблице. Как сказал Рихо, посмотрите тесты.

Стол будет легче интернационализировать. Но так же будет класс вне базы данных полностью. Этот вид проверки может быть сложным для отладки, когда он не входит в бизнес-логику, и, как правило, не входит в обязанности сотрудников базы данных.

Как оптимизация, это, вероятно, очень преждевременно; но OP в основном предлагает его как удобную функцию в любом случае.

Смотрите также http://komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil/

Другие вопросы по тегам