Вопрос дизайна базы данных - PullRequest
8 голосов
/ 09 сентября 2010

У меня есть форма, где пользователи отправляют различные поля для создания событий. Количество и тип запрашиваемых полей различны в каждой форме, в зависимости от категории события. Каков наилучший способ разработки этой базы данных - должны ли события содержать все возможные поля и просто обнулять неиспользуемые поля? Спасибо!

Ответы [ 4 ]

5 голосов
/ 10 сентября 2010

Если вы начнете учитывать совет Джоэла, перейдите по ссылке здесь .

или здесь

или здесь

И если вы не верите ни одному из них, постройте 4 таблицы, о которых он упоминает. Там только 4, это не займет много времени. Затем загрузите некоторые данные в них ... затем попробуйте написать запросы, которые вы хотите написать ...

Изменение столбца означает:

Это может сильно повлиять на оценку количества элементов. Ваши тарелки могут быть в диапазоне от 4 до 20, места для концертов - от 1000 до 2000. Некоторые расчеты кардинальности учитывают разброс от минимума до максимума и предполагают равное распределение (при отсутствии другой статистики) ...

От 4 до 2000 означает, что где-нибудь GENERIC_COLUMN = n,% строк, по которым вы попадете, составляет 1/16 от общей суммы ... но на самом деле, если бы вы сказали, где EVNT_TYPE = Dinner и GENERIC_COLUMN = n, это ДЕЙСТВИТЕЛЬНО будет от 4 до 20, или 1/16 от общего количества строк ... так что огромная разница в оценке карты. (Это можно исправить с помощью гистограмм, но смысл показа проблем автоматизации состоит в том, чтобы просто подчеркнуть, что если это проблема для машины, она, вероятно, не так чиста, как могла бы быть.)

Так что, если бы вы сделали это (НАМНОГО ЛУЧШЕ, чем EAV, но ...)

Я бы порекомендовал создать представление для каждого объекта.

Таблица EVENT (общие поля, Generic_Count) Просмотр DINNER (общие поля, Generic_Count в виде тарелок) WHERE type = Dinner Просмотр CONCERT (общие поля, Generic_Count as Seats) ГДЕ тип = Концерт

Тогда НЕ БУДЬТЕ ВЫБРАТЬ против СОБЫТИЯ

Но именно здесь вы попадаете в беду, НЕ начав сначала с концептуальной модели данных.

У вас будет ENTITY для EVENT, а другой для DINER, который полностью наследует от EVENT, и другой для CONCERT, который полностью наследует от EVENT. Затем вы можете установить дифференцирующий столбец в объекте наследования, который позволит вам установить столбец «TYPE», а затем вы даже сможете решить, сколько таблиц построить, одним щелчком переключателя. 1 стол, 2 стола или 3 стола.

По крайней мере, вы можете сделать это в powerDesigner.

Почему DDL считается таким плохим?

Создание моделей EAV и подобные вопросы организованы вокруг идеи, что DDL следует избегать. Зачем ALTER TABLE, когда вы можете ВСТАВИТЬ новую строку атрибута? Люди принимают плохие решения по проектированию моделей данных, основываясь на неправильной служебной функции. Это такие функции, как «нет столбцов, которые можно обнулять», «чем меньше таблиц, тем лучше», «нет ddl, просто чтобы добавить новый атрибут». Вместо этого вставьте в таблицу атрибутов '.

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

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

В вашем случае, вы когда-нибудь хотели бы знать все события, которые вы добавили за последние 2 недели? Теперь подумайте о возможных моделях. Одна таблица для каждого типа события будет означать суммирование по n таблицам, чтобы найти этот ответ, и с каждым новым типом события будет добавляться новая таблица, и каждый запрос «Все события» будет меняться. Вы можете создать UNION ALL представление этих таблиц, но вам нужно помнить, чтобы добавлять каждую новую таблицу в представление. Отладка таких представлений - это боль.

Предполагая, что вам может потребоваться множество метрик для ВСЕХ событий, одна таблица имеет больше смысла (по крайней мере, для некоторой общей части ваших данных о событиях - таких как имя события, идентификатор спонсора, идентификатор места, время начала события, время окончания события , место, доступное для времени установки и т. д.) Эти поля (давайте оговорим) являются общими для каждого события.

Так что теперь делать с другими столбцами? Два варианта, обнуляемые поля или вертикальное разбиение таблицы. Последнее является оптимизацией первого. И если вы читаете какие-либо книги или блоги по оптимизации баз данных, главное, что я извлекаю из них, это то, что преждевременная оптимизация убивает. Я вижу, как люди реализуют множество стратегий для решения проблем, прежде чем они узнают, будет ли у них такая проблема. У сотрудника был медленный запрос, с которым он хотел, чтобы я помог. Он был загружен подсказками оптимизатора. Я удалил их, и SQL закричал ... Я не знаю, ПОЧЕМУ он намекнул, но он не делал этого эффективно, и я уверен, что он никогда не видел проблемы, так что это всего лишь преждевременная оптимизация.

Вертикальное разбиение - это то, что вы делаете, когда у вас большие объемы данных, и у вас есть некоторые часто используемые данные и другие данные, которые не очень полезны. Вы можете упаковать стол с гораздо меньшим количеством блоков, если вы упакуете только часть общего достояния. Больше строк на блок = более быстрое сканирование таблиц ... на самом деле не влияет на скорость поиска отдельной строки по индексу. Как вы можете видеть, вертикальное разбиение имеет определенную проблему, которую оно может решить (другие тоже, например, цепочки строк), поэтому, если вы уверены, что это ПРОБЛЕМА, тогда непременно начинайте именно так.

1 голос
/ 09 сентября 2010

Я бы тщательно подумал об этой абстракции, но у вас также может быть связанная таблица, содержащая подробности события:

Table Event:  id, Name

Table EventDetail:  id, EventID, DetailFieldName, DetailText

Одна Event запись может иметь много EventDetail записей.

Это гибкий, но опять же есть компромиссы для рассмотрения. Ваши запросы будут усложняться, и представление результатов будет иметь дополнительный уровень косвенности (для представления всей этой записи необходимо просмотреть все записи EventDetail для конкретной записи Event).

Вы можете сделать все возможное, а также нормализовать DetailFieldName в таблицу EventDetailField, если хотите.

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

Выбери свой яд. ;) Нормализация имеет свое место, но я также обнаружил, что она усложняет определенные задачи, если вы слишком много нормализуете.

0 голосов
/ 09 сентября 2010

Вы должны максимально нормализовать свою таблицу, чтобы уменьшить количество нулей в базе данных.Записи должны быть значимыми, если они хранятся.Одним из методов может быть таблица категорий, которая связывает 1-> m с таблицей событий.Тогда вы можете иметь таблицу ожидаемых полей в формах (присваивая каждому int id).Затем в промежуточной таблице будут храниться фактические представленные данные.

catID|Category
 |
 --------------------
                    |
eventID | event | catID
 |
 ------------------------------
                     |        |
fldID | fldName | eventID     |
 |                            |
 -----------        -----------
           |        |
dataID | fldID | eventID | data
0 голосов
/ 09 сентября 2010

Это зависит от того, насколько сильно отличаются ваши формы.Я говорю, есть разные поля для каждого элемента ввода ... наличие 1 поля с несколькими элементами просто усложнит запросы.Если ваши формы не слишком отличаются, то 1 таблица с каждым возможным полем будет в порядке, но если ваша таблица содержит более 20 полей, я бы предложил разделить эти таблицы.Я бы также порекомендовал таблицу заголовков с полем «тип формы» для облегчения поиска.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...