Подтвердить что ты не робот

MySQL ENUM type vs join tables

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

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

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


начальный дизайн

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

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

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

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

4b9b3361

Ответ 1

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

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

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

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

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

Обновление: MySQL 8.0.16 теперь реализует ограничения CHECK.

Ответ 2

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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

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