Отношение многие ко многим: использовать ассоциативную таблицу или значения с разделителями в столбце? - PullRequest
16 голосов
/ 24 апреля 2009

Обновление 2009.04.24

Суть моего вопроса не в замешательстве разработчиков, а в том, что с этим делать.

Смысл в том, чтобы понять, когда значения с разделителями являются правильным решением.

Я видел данные с разделителями, используемые в коммерческих базах продуктов (Ektron lol).

SQL Server даже имеет тип данных XML, поэтому его можно использовать для тех же целей, что и поля с разделителями.

/ конец обновления

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

Вот пример структуры БД:

Document
---------------
ID (PK)
Title
CategoryIDs (varchar(4000))


Category
------------
ID (PK)
Title

Между документом и категорией существует отношение многие ко многим.

В этой реализации Document.CategoryIDs представляет собой большой разделенный по конвейеру список CategoryID.

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

С этой моделью, чтобы получить все документы для категории, вам понадобится что-то вроде следующего:

select * from documents where categoryids like '%|' + @targetCategoryId + '|%'

Мое решение - создать ассоциативную таблицу следующим образом:

Document_Category
-------------------------------
DocumentID (PK)
CategoryID (PK)

Это сбивает с толку разработчиков. Есть ли какое-нибудь элегантное альтернативное решение, которое мне не хватает?

Я предполагаю, что в Document будут тысячи строк. Категория может быть как 40 строк или около того. Основной проблемой является производительность запросов. Я переусердствовал в этом?

Есть ли случай, когда предпочтительнее хранить списки идентификаторов в столбцах базы данных, а не помещать данные в ассоциативную таблицу?

Учтите также, что нам может понадобиться создать отношения «многие ко многим» между документами. Это предполагает ассоциативную таблицу Document_Document. Это предпочтительный дизайн или лучше хранить связанные идентификаторы документов в одном столбце?

Спасибо.

Ответы [ 9 ]

34 голосов
/ 24 апреля 2009

Это сбивает с толку разработчиков.

Получить лучших разработчиков. Это правильный подход.

25 голосов
/ 24 апреля 2009

Ваше предложение - элегантное, мощное, передовое решение.

Поскольку я не думаю, что в других ответах достаточно четко сказано следующее, я собираюсь это сделать.

Если ваши разработчики 1) не могут понять, как смоделировать отношение «многие ко многим» в реляционной базе данных, и 2) настойчиво настаивают на сохранении ваших CategoryID в качестве символьных данных с разделителями,

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

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

Надеюсь, этот ответ очень полезен для вас.

Обновление

Суть моего вопроса не в замешательстве разработчиков, а в том, что с этим делать.

Смысл в том, чтобы понять, когда значения с разделителями являются правильным решением.

Значения с разделителями являются неправильным решением, за исключением крайне редких случаев. Когда отдельные значения когда-либо запрашиваются / вставляются / удаляются / обновляются, это доказывает, что это было неправильное решение, потому что вам нужно проанализировать и коснуться всех других значений просто для работы с желаемым. Делая это, вы нарушаете first (!!!) нормальную форму (эта фраза должна звучать для вас как невероятно гнусное ругательство). Использование XML, чтобы сделать то же самое, тоже неправильно. Хранение значений с разделителями или XML с несколькими значениями в столбце может иметь смысл, когда он рассматривается как неделимый и непрозрачный «пакет свойств», который НЕ запрашивается базой данных, но всегда отправляется целиком другому потребителю ( возможно, веб-сервер или получатель EDI).

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

Я допускаю, что есть несколько довольно сложных реализаций хранения нереляционных данных с использованием пакетов текстовых свойств (таких как Facebook (?) И другие многомиллионные сайты пользователей, работающие на тысячах серверов). Когда ваша база данных, пользовательская база и количество транзакций в секунду достаточно велики, вам понадобятся деньги для ее разработки. А пока придерживайтесь лучших практик.

17 голосов
/ 24 апреля 2009

Почти всегда большая ошибка использовать идентификаторы через запятую.
СУБД предназначены для хранения отношений.

16 голосов
/ 24 апреля 2009

Мое решение - создать Ассоциативная таблица выглядит следующим образом: сбивает с толку разработчиков

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

То, что вы предлагаете, является правильным решением !!

11 голосов
/ 24 апреля 2009

Таблица Document_Category в вашем дизайне, безусловно, является правильным способом решения проблемы. Если это возможно, я бы посоветовал вам обучать разработчиков вместо того, чтобы придумывать неоптимальное решение (и с ударом по производительности, и без ссылочной целостности).

Другие параметры могут зависеть от базы данных, которую вы используете. Например, в SQL Server у вас может быть столбец XML, который позволит вам хранить ваш массив в предварительно определенной схеме, а затем выполнять объединения на основе содержимого этого поля. Другие системы баз данных могут иметь нечто подобное.

6 голосов
/ 24 апреля 2009

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

Если вы действительно хотите использовать структуру списка, используйте СУБД, которая их понимает. Примерами таких баз данных могут быть СУБД U2 (Unidata, Universe), которые (или были когда-то давно) основаны на СУБД Pick. Скорее всего, есть другие похожие поставщики СУБД.

6 голосов
/ 24 апреля 2009

Отображение «многие ко многим», которое вы делаете, нормально и нормализовано. Это также позволяет добавлять другие данные позже, если это необходимо. Например, допустим, вы хотите добавить время, когда категория была добавлена ​​в документ.

Я бы предложил иметь суррогатный первичный ключ в таблице document_category. И ограничение Unique (documentmentid, categoryid), если это имеет смысл.

Почему разработчики запутались?

5 голосов
/ 09 мая 2009

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

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

Возможно, как и в одном из моих проектов, разработчики имели таблицу для размещения значений multi, но у них сложилось впечатление, что дублирование этих данных в родительской таблице ускорит производительность. , Они были неправы, и их вызвали на это.

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

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

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

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

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

5 голосов
/ 24 апреля 2009

Это классическая проблема объектно-реляционного отображения. Разработчики, вероятно, не глупы, просто неопытны или не привыкли делать все правильно. Крик "3NF!" снова и снова не убедит их в правильности пути.

Я предлагаю вам попросить ваших разработчиков объяснить вам, как они будут получать количество документов по категориям, используя подход с разделителями каналов. Это было бы кошмаром, тогда как таблица ссылок делает это довольно простым.

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