Работа с «гипернормализованными» данными - PullRequest
4 голосов
/ 03 февраля 2009

Мой работодатель, небольшая канцелярская компания, меняет поставщиков, и я просматриваю их электронный контент, чтобы найти надежную схему базы данных; наша предыдущая схема была в значительной степени просто собрана вместе, не задумываясь, и в значительной степени привела к невыносимой модели данных с поврежденной, противоречивой информацией.

Данные нового поставщика намного лучше, чем у старого, но их данные - это то, что я бы назвал гипернормализованным . Например, их структура категории продуктов имеет 5 уровней: главный отдел, отдел, класс, подкласс, блок продукта. Кроме того, содержимое блока продукта содержит подробное описание, поисковые термины и названия изображений для продуктов (идея состоит в том, что блок продукта содержит продукт и все варианты - например, конкретная ручка может быть выполнена черными, синими или красными чернилами; все они Предметы по сути одно и то же, поэтому они относятся к одному блоку товара). В данных, которые мне предоставили, это выражается в виде таблицы продуктов (я говорю «таблица», но это простой файл с данными) со ссылкой на уникальный идентификатор блока продукта.

Я пытаюсь придумать надежную схему для размещения данных, которые мне предоставлены, поскольку мне нужно будет загрузить их относительно скоро, и данные, которые они мне дали, не соответствуют типу данных, которые они предоставляют для демонстрации на своем образце веб-сайта (http://www.iteminfo.com). В любом случае, я не собираюсь повторно использовать их структуру представления, поэтому это спорный вопрос, но я просматривал сайт, чтобы получить некоторые идеи о том, как структурировать вещи.

В чем я не уверен, так это в том, хранить ли данные в этом формате или нет, или, например, объединить Master / Department / Class / Subclass в одну таблицу «Категории», используя самореферентную связь и ссылку это для блока продукта (блок продукта должен храниться отдельно, поскольку это не «категория» как таковая, а группа связанных продуктов для данной категории). В настоящее время таблица блоков продукта ссылается на таблицу подклассов, поэтому она будет изменена на "category_id", если я объединю их вместе.

Я, вероятно, собираюсь создать витрину электронной коммерции, используя эти данные с Ruby on Rails (или это мой план, во всяком случае), поэтому я стараюсь не зацикливаться позже или иметь раздутые приложения - может быть, я слишком много об этом думаю, но лучше быть в безопасности, чем сожалеть; наши предыдущие данные были настоящей неразберихой и стоили компании десятки тысяч долларов в потерянных продажах из-за непоследовательных и неточных данных. Также я собираюсь немного отойти от соглашений Rails, убедившись, что моя база данных является надежной и применяет ограничения (я планирую делать это и на уровне приложений), так что это тоже нужно учитывать.

Как бы вы справились с такой ситуацией? Имейте в виду, что у меня есть данные для загрузки уже в виде плоских файлов, которые имитируют структуру таблицы (у меня есть документация, в которой говорится, какие столбцы какие и какие ссылки установлены); Я пытаюсь решить, следует ли мне сохранить их в таком же нормированном виде, как они есть в настоящее время, или мне следует попытаться объединить их; Мне нужно знать, как каждый метод будет влиять на то, как я программирую сайт с использованием Rails, поскольку, если я произвожу консолидацию, в одной таблице будет по существу 4 «уровня» категорий, но это определенно кажется более управляемым, чем отдельные таблицы для на каждом уровне, поскольку, кроме Подкласса (который напрямую связан с блоками продуктов), они не делают ничего, кроме как показывают следующий уровень категории под ними. Я всегда теряюсь из-за «лучшего» способа обработки данных, подобных этому - я знаю поговорку «нормализуй, пока не повредит, затем денормализуй, пока не заработает», но мне никогда не приходилось реализовывать это до сих пор.

Ответы [ 10 ]

6 голосов
/ 03 февраля 2009

Я бы предпочел «гипернормализованный» подход по сравнению с ненормальной моделью данных. Упомянутая вами таблица собственных ссылок может уменьшить количество таблиц и в некоторых отношениях упростить жизнь, но в целом с этим типом отношений может быть сложно справиться. Иерархические запросы становятся проблемой, как и сопоставление объектной модели с этим (если вы решите пойти по этому пути).

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

3 голосов
/ 03 февраля 2009

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

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

Компромисс - это небольшая дополнительная сложность в БД (таблица замыкания и триггеры) для гораздо меньшей сложности в пользовательском интерфейсе и коде бизнес-уровня.

2 голосов
/ 03 февраля 2009

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

2 голосов
/ 03 февраля 2009

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

Как правило, denormalization имеет цель быстрее querying, но приводит к увеличению пространства, увеличению DML времени и, что не менее важно, к увеличению усилий по обеспечению согласованности данных.

Обычно пишется код быстрее (пишет быстрее, а не код быстрее), и код менее подвержен ошибкам, если данные normalized.

2 голосов
/ 03 февраля 2009

Если я правильно понимаю, вы хотите взять их отдельные таблицы и превратить их в иерархию, которая хранится в одной таблице с самосвязанной FK.

Как правило, это более гибкий подход (например, если вы хотите добавить пятый уровень), НО SQL и реляционные модели данных не склонны хорошо работать со связанными списками, подобными этому, даже с новым синтаксисом, таким как MS SQL Серверы CTE. По общему признанию, CTE делают это намного лучше все же.

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

Если вы решите сделать это таким образом, то обязательно ознакомьтесь с SQL для умников Джо Селко , в котором, я считаю, есть один или два раздела о моделировании и работе с иерархиями в SQL или, что еще лучше, но получите книга, посвященная этой теме ( Деревья и иерархии Джо Селко в SQL для умников ).

1 голос
/ 03 февраля 2009

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

Лучше ввести свои данные, выполнить проверку работоспособности и убедиться, что предположения не нарушены. Затем, если у вас есть модель для конкретного приложения, преобразуйте ее в модель для оптимального использования вашим приложением.

0 голосов
/ 28 февраля 2013

Каждый, кто рекомендует вам не вводить иерархию в базе данных, рассматривает только вариант наличия таблицы с самоссылкой. Это не единственный способ моделирования иерархии в базе данных. Вы можете использовать другой подход, который обеспечивает более простой и быстрый запрос без использования рекурсивных запросов. Допустим, у вас есть большой набор узлов (категорий) в вашей иерархии:

Set1 = (Node1 Node2 Node3 ...)

Любой узел в этом наборе также может быть другим набором, который содержит другие узлы или вложенные наборы:

Узел1 = (Узел2 Узел3 = (Узел4 Узел5 = (Узел6) Узел7))

Теперь, как мы можем смоделировать это? Давайте каждый узел будет иметь два атрибута, которые устанавливают границы узлов, которые он содержит:

Node = {Id: int, Min: int, Max: int}

Чтобы смоделировать нашу иерархию, мы просто назначаем эти минимальные / максимальные значения соответственно:

Node1 = {Id = 1, Min = 1, Max = 10}
Node2 = {Id = 2, Min = 2, Max = 2}
Node3 = {Id = 3, Min = 3, Max = 9}
Node4 = {Id = 4, Min = 4, Max = 4}
Node5 = {Id = 5, Min = 5, Max = 7}
Node6 = {Id = 6, Min = 6, Max = 6}
Node7 = {Id = 7, Min = 8, Max = 8}

Теперь, чтобы запросить все узлы в Set / Node5:

выберите n. * Из узлов как n, узлов как s
где s.Id = 5 и s.Min

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

0 голосов
/ 24 ноября 2010

Для меня реальный вопрос: что лучше подходит для модели?

Это как сравнивать кортеж и список.

  1. Кортежи имеют фиксированный размер и неоднородны - они "гипернормализованы".
  2. Списки имеют произвольный размер и являются однородными.

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

В этом случае, так как структура продукта уже четко определена (и я предполагаю, что вряд ли изменится), я бы придерживался «подхода Tuple». Реальная сила / использование Списка (или рекурсивного шаблона таблицы) - это когда вам нужно развернуть на произвольную глубину, например, для спецификации или дерева генеалогии.

Я использую оба подхода в некоторых моих базах данных в зависимости от необходимости. Однако существует также «скрытая стоимость» рекурсивного шаблона, заключающаяся в том, что не все ORM (не уверены в AR) поддерживают это хорошо. Многие современные БД поддерживают "сквозные соединения" (Oracle), идентификаторы иерархии (SQL Server) или другие рекурсивные шаблоны. Другой подход заключается в использовании иерархии, основанной на множестве (которая обычно опирается на триггеры / обслуживание). В любом случае, если используемый ORM плохо поддерживает рекурсивные запросы, то могут возникнуть дополнительные «затраты» на непосредственное использование функций для БД - либо с точки зрения генерации запросов / представлений вручную, либо с точки зрения управления, таких как триггеры. Если вы не используете классный ORM или просто используете логический разделитель, такой как iBatis, эта проблема может даже не применяться.

Что касается производительности, то на новых СУБД Oracle или SQL Server (и, вероятно, на других) она должна быть очень сопоставимой, так что это будет наименьшим из моих беспокойств: но посмотрите решения, доступные для вашей СУБД и проблем переносимости.

0 голосов
/ 24 ноября 2010

всегда ли ваш магазин (или что бы вы ни строили, не совсем ясно) будет использовать данные этого поставщика? Вы могли бы когда-нибудь поменять поставщиков или добавить других разных поставщиков?

если это так, разработайте общую схему, которая отвечает вашим потребностям, и сопоставьте с ней данные поставщика. Лично я предпочел бы перенести (невероятно незначительную) «боль» самореферентной таблицы категорий (иерархической), чем поддерживать четыре (очевидно, наполовину бесполезных) уровня вариантов категорий, а затем в следующем году узнаю, что они добавили 5-й или представил линейку продуктов только с тремя ...

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

Не денормализовать. Попытка получить хороший дизайн схемы путем денормализации - это все равно, что попытаться добраться до Сан-Франциско, уезжая из Нью-Йорка. Он не говорит вам, куда идти.

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

Как только вы узнаете, как должна выглядеть нормализованная схема, вам необходимо выяснить, как разработать схему, соответствующую вашим потребностям. Если эта схема несколько не полностью нормализована, пусть будет так. Но будьте готовы к трудностям в программировании преобразования между данными в сведенных файлах и данными в вашей разработанной схеме.

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

...