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

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

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

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


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

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

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

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

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

12.12.2008 06:34:36
Тип данных ENUM начинается с 1, а не с 0, как вы указали.
Tomalak 12.12.2008 06:46:47
Tomalak 12.12.2008 06:47:38
5 ОТВЕТОВ
РЕШЕНИЕ
  • Изменение набора значений в ENUM требует того, ALTER TABLEчто может вызвать реструктуризацию таблицы - невероятно дорогая операция (реструктуризация таблицы не произойдет, если вы просто добавите одно новое значение в конец определения ENUM, но если вы удалите его или изменить порядок, он выполняет реструктуризацию таблицы). Принимая во внимание, что изменение набора значений в таблице поиска так же просто, как INSERT или DELETE.

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

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

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

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

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

98
21.05.2019 15:17:24
Спасибо Билл за ваши советы. Иногда такие абстракции, как тип ENUM, могут выглядеть просто и элегантно, но это административная бомба замедленного действия.
ashitaka 12.12.2008 07:05:55
О, я забыл один: ENUM не является стандартным SQL и AFAIK, ни одна другая база данных не поддерживает его. Так что это ограничивает вашу мобильность, если вы используете его.
Bill Karwin 12.12.2008 07:07:33
Кто-то дал мне отрицательный голос. Когда вы даете отрицательные голоса, не могли бы вы объяснить, что вы возражаете? Возможно, я смогу улучшить ответ.
Bill Karwin 8.11.2010 20:46:04
Вам не нужно использовать INFORMATION_SCHEMA. Используйте DESC table, просматривайте результаты, пока не найдете нужное поле, и используйте регулярное выражение для получения полей. Это не очень хорошая вещь, но это не так уж плохо.
Ariel 11.07.2012 04:22:18
Я нашел другое интересное объяснение: komlenic.com/244/8-reasons-why-mysqls-enum-data-type-is-evil
Zbyszek 6.06.2013 05:59:24

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

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

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

-1
28.10.2018 22:30:53

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

12
27.02.2020 16:19:57

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

Моя точка зрения о крошечных:

  • перечисления ограничены 65535 значениями
  • если вам не нужно больше 256 значений, tinyint будет занимать меньше места для каждой строки, и его поведение будет гораздо более «предсказуемым».
7
21.02.2020 05:42:01
Подожди, так плохи ли enums или tinyint? Или оба?
Brad Moore 21.01.2014 02:38:21
Совершенно уверен, что он хотел сказать «перечисления» плохо по объясненным причинам.
abenson 7.01.2015 19:53:59
По крайней мере, в MySQL, если вы установите SQL_MODE в одну из строгих форм, вы не получите ноль или '', если попытаетесь вставить значение, которого нет в ENUM. Вы получите ошибку. См. Dev.mysql.com/doc/refman/5.7/en/constraint-enum.html
Bill Karwin 28.03.2016 21:17:28

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

3
18.11.2010 18:23:11