Нормализация базы данных MySQL

Должен ли я реализовать нормализацию чтения базы данных (с помощью таблиц соединения) или использовать тип ENUM для статических или динамических данных?

Например:

У меня есть таблица USER с user_status. Должен ли я создать таблицу status или создать список ENUM со статусами?

Спасибо Г


person Gino Sullivan    schedule 26.10.2011    source источник


Ответы (3)


ИМХО, расширение enum значительно упрощает встраивание семантики в таблицу, а также повышает эффективность за счет:

  1. уменьшение количества объединений, необходимых для запроса
  2. уменьшение количества открытых таблиц в СУБД

Единственные недостатки, о которых я знаю, это

  1. тип ENUM не реализован другими СУБД
  2. если вы решите добавить дополнительные значения в набор ENUM позднее, вы применяете обновление DDL, что может занять много времени с очень большой таблицей.

ХТН

C.

person symcbean    schedule 27.10.2011
comment
Тест производительности: mysqlperformanceblog.com/2008/01/24/ - person ypercubeᵀᴹ; 27.10.2011
comment
Есть и другие проблемы с ENUM. Во-первых, все столбцы ENUM могут принимать специальное неизвестное значение пустой строки (в дополнение к NULL, если это разрешено); кроме того, это значение будет использоваться для любого присвоения недопустимого значения, если только не используется строгий режим SQL. Это может привести к непреднамеренной несогласованности базы данных; Кроме того, если в списке ENUM имеется явное пустое строковое значение, это может привести к огромной путанице (поскольку необходимо проверить числовое значение, чтобы определить, какой тип пустой строки хранится). - person eggyal; 25.04.2013
comment
Кроме того, неявное преобразование в числовые значения в числовых контекстах может вызвать значительную путаницу, особенно если кто-то пытается использовать строки, представляющие числа как значения ENUM. В руководстве приводится хороший пример списка ENUM ('0','1','2'): Если вы сохраняете 2, оно интерпретируется как значение индекса и становится '1' (значение с индексом 2). Если вы сохраняете '2', оно соответствует значению перечисления, поэтому оно сохраняется как '2'. Если вы сохраняете '3', оно не соответствует никакому значению перечисления, поэтому оно рассматривается как индекс и становится '2' (значение с индексом 3). - person eggyal; 25.04.2013
comment
Наконец, ENUM может вызвать путаницу в контексте сортировки, поскольку значения сортируются в соответствии с их положением в списке ENUM (в то время как можно ожидать, что значения будут отсортированы лексикографически). Хотя я бы не стал заходить так далеко, как 8 причин, почему тип данных ENUM в MySQL является злом, я определенно думаю, что его статью стоит прочитать, чтобы понять проблемы; и, учитывая, что объединение должным образом проиндексированных таблиц должно быть столь же (если не более) эффективным, чем ENUM, я не вижу в этом реальных преимуществ. - person eggyal; 25.04.2013
comment
@eggyal: Спасибо за ссылку - это интересно, но, похоже, немного устарело. Что касается значения «неизвестно» - невозможно воспроизвести это в 5.0.22 - можно сделать только значение NULL (если это разрешено таблицей определение). - person symcbean; 07.11.2013
comment
По поводу implicit conversion to numeric values - опять не удалось воспроизвести. Попытка вставить целочисленное значение в столбец enum дала ошибку # 1064, когда я попытался это сделать. - person symcbean; 07.11.2013
comment
Что касается can cause confusion in sorting - все известные мне языки с поддержкой enum либо используют порядок объявления в качестве индикатора последовательности (C, Fortran, Java, MySQL), либо рассматривают значения как чисто непорядковые (т.е. номинальные). Если вам явно нужно упорядочение на основе метки, а не ее внутреннего представления, это не сложно (ORDER BY concat(enumd)) - откровенно говоря, любой, кто не знает, как их инструменты управляют вводом текста, заслуживает всего, что они получают;) - person symcbean; 07.11.2013
comment
Относительно двух проблем, которые вам не удалось воспроизвести: включен ли строгий режим SQL? Что касается проблемы сортировки, вы правы и в том, что большинство людей должны ожидать такого поведения, и что существуют обходные пути, но такие обходные пути не могут использовать какой-либо индекс, определенный для столбца, и, следовательно, могут оказаться очень затратным. - person eggyal; 07.11.2013

Другая вещь, которую следует учитывать...

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

person Guilhem Hoffmann    schedule 27.10.2011

Это зависит от архитектуры и многих других факторов.

Например, вы не разрешаете чтение/запись данных, кроме как с использованием хранимых процедур. В этом случае вы можете свободно использовать тип данных «tinyint». Если вы разрешаете чтение/запись с прямыми запросами, лучше использовать ограничение, то есть ENUM, чтобы избежать неправильных статусов (если, конечно, пользовательский интерфейс или серверная часть могут поставить этот «неправильный» статус).

С другой стороны (и это возможно) могут быть изменения в потоке данных и, возможно, вам нужно будет добавить новые статусы. В этом случае вам потребуется: 1) ничего не делать, если у вас статический тип данных; 2) измените, если у вас есть ENUM.

Итак... мой ответ: это зависит от вашего приложения и ваших требований.

person ravnur    schedule 27.10.2011
comment
Вы также можете применять правильные статусы с помощью ограничений внешнего ключа (используя таблицы innodb). - person Inca; 27.10.2011
comment
... и создайте еще одну таблицу. Я думаю, что чрезмерная нормализация (иметь одну дополнительную таблицу для каждого статуса) в целом не является хорошим подходом. - person ravnur; 27.10.2011
comment
Не могли бы вы объяснить, почему нет? Нет проблем с наличием большого количества столов. (И они обеспечивают дополнительную гибкость, например, добавление редактируемых описаний к статусу или отключение одного для новых записей, но сохранение его для старых записей.) - person Inca; 27.10.2011
comment
потому что им нужны изменения. Это не проблема для маленького стола, но большая проблема для большого. - person ravnur; 27.10.2011
comment
что ты имеешь в виду под "изменяет"? Для создания перечислений также требуется оператор alter, но, возможно, вы имеете в виду не это? - person Inca; 27.10.2011
comment
Я имею в виду, когда вы будете применять какие-либо изменения в логике/потоке данных (т.е. добавлять пару статусов), вам нужно будет изменить этот столбец. Когда вы не используете ENUM, вам не нужно делать изменения, чтобы добавить новый статус. - person ravnur; 28.10.2011