Обсуждение структуры базы данных управления судном (следует ли денормализовать?) - PullRequest
1 голос
/ 12 февраля 2009

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

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

Я решил проблему с помощью следующих таблиц

Ship:
- ID - smallint, Autoincrement identity
- IMO - int, A number that does not change for the life of the ship

ShipDetailType: 
- ID - smallint, Autoincrement identity
- Description - nvarchar(200), The description of the value the field contains
- Position - smallint, The position of the field in the data input form
- ShipDetailGroup_ID - smallint, A key to the group the field belongs to in the data input form
- Type - varchar(4), The type of the field as mentioned above

ShipDetailGroup
- ID - smallint, Autoincrement identity
(snip...)

ShipMenuPresetValue
- ID - smallint, Autoincrement identity
- ShipDetailType_ID - smallint, A key to the detail the values belongs to
- Value - nvarchar(100), The values preset in the menu type detail

ShipTextDetail
- ID - smallint, Autoincrement identity
- Ship_ID - smallint, A Key to the ship the detail belongs to
- ShipDetailType_ID - smallint, a Key to the detail type of the value
- Text - nvarchar(500), the field containing the detail's value
- ModifiedDate - smalldatetime
- User_ID - smallint, A key to the user table

ShipTextDetailHistory
(snip...) 
This table is the same as the ShipTextDetail and contains every change to the details.

Other tables for the list detail type, each with the specified fields required for the list, ...

Я только что прочитал эту статью: http://thedailywtf.com/Articles/The_Inner-Platform_Effect.aspx и http://asktom.oracle.com/pls/asktom/f?p=100:11:0::::P11_QUESTION_ID:10678084117056

В статьях говорится, что это неправильный способ решения проблемы.

У моего клиента есть интерфейс управления для деталей и групп, так как он меняет описания деталей и добавляет дополнительные детали.

Форма ввода данных динамически создается путем чтения структуры из DetailGroups и DetailTypes, каждый тип детализации генерирует указанный элемент управления вводом.

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

Что вы думаете?

Снимок экрана: http://img24.imageshack.us/my.php?image=66604496uk3.png

Ответы [ 4 ]

4 голосов
/ 12 февраля 2009

Я видел этот подход раньше, и он представил множество проблем с производительностью, как только объем данных вырос. Проблемы, с которыми вы столкнетесь, возникают, когда вам нужно вернуть несколько элементов и использовать несколько критериев в предложении where. Вы объединяетесь между Ship и ShipTextDetail, чтобы получить все выбранные вами столбцы - может быть, вам придется делать это 10/20 раз? Затем вы делаете то же самое для ваших критериев, может быть, 2-3 раза. Теперь у вас есть запрос с таким количеством соединений, он выполняется очень медленно. Затем вы «предварительно готовите» некоторые данные для повышения производительности, то есть перетаскиваете общие данные в фиксированную структуру таблицы - а вы вернулись к полунормализованной модели.

Моя рекомендация была бы такова - вы знаете информацию для 174 полей, которые являются вашими основными атрибутами. Ваш клиент может добавить в этот список и может изменить описание полей, но это по-прежнему хорошая отправная точка. Создайте соответствующую DataModel, основанную на них, и затем встроите механизм расширяемости, как вы уже сделали, но только для новых полей. Метаданные - описания полей, могут находиться в другой таблице или, возможно, в файле ресурсов (полезно для интернационализации?), Что дает некоторую гибкость для существующих полей.

Я согласен с Джо, у вас могут не быть проблем, если ваша БД мала, то есть <1000 кораблей и ваш выбор прост. Хотя из 174 атрибутов на выбор это вряд ли возможно. Я думаю, что вам следует сначала изменить некоторые из «очевидных» полей, то есть я бы предположил, что у вас есть Ship.Name, Ship.Owner, Ship.Weight, Ship.Registration ... </p>

Удачи.

4 голосов
/ 12 февраля 2009

Я бы рефакторил ваш код, если:

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

Вы не забыли писать модульные тесты, которые позволят вам проводить рефакторинг, верно?

* Что касается имеющейся у вас структуры, я уже видел подобные структуры. Это немного громоздко, но это стандарт во многих местах. Следует помнить одну вещь: хотя возможно динамическое добавление и удаление столбцов из баз данных, механизм внутреннего хранения базы данных не обязательно предполагает непрерывное добавление и удаление этих столбцов. Но я не думаю, что это очень актуально по сравнению с пунктами выше, которые сводятся к: * Работает ли?

0 голосов
/ 12 февраля 2009

С точки зрения производительности любой подход будет нормальным. Сколько кораблей там может быть? Все данные помещаются в оперативную память на любом сервере.

0 голосов
/ 12 февраля 2009

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

  1. Вы храните числа, логические значения, даты и т. Д. В виде строк. Это может быть не идеально. Альтернативой является реализация отдельных классов (наследуемых от базы) для разных типов данных, а затем их сохранение в таблицах, созданных для их типа данных.
  2. Изменяются ли свойства, которые вы отслеживаете, очень часто? Они разные наборы на танкер? Если нет, то лучше хранить объекты, а не пакеты свойств, чтобы хранить все данные. Затем эти объекты можно сохранить в базе данных.
...