Как стать автором
Обновить

Комментарии 51

Если я правильно понял мысль, то это просто 2 разные нормальные формы таблиц.
Да, разумеется. Просто хочется услышать плюсы и минусы каждой из реализаций. Одни из самых явных — на добавление нового типа объекта в первом варианте будет портачено гораздо меньше времени, чем во втором (быстрая расширяемость).
НЛО прилетело и опубликовало эту надпись здесь
Из коммерческих CMS такую реализацию выбрали UMI.CMS и Netcat, поэтому, изучив эти системы, мне и пришло в голову посоветоваться с Хабрасообществом. Спасибо за совет ;-).
Пред-рас-судки.
«Уровень требуемой квалификации» — вот именно. Это не ущербная попытка. Это не каждому быдлокодеру доступный вариант.
Если мы говорим о реляционных БД, то первый вариант имеет очень ограниченное применение. Да это универсально, но за универсальность надо платить, в данном случае, производительностью.
присоединяюсь к Вашему мнению.
более того, если мы говорим о первом варианте, нас совершенно не интересует, является ли СУБД реляционной.
Если хочется объектную бд, то нужно пользоваться хотя бы ORDMS (объектно-реляционная) PostgreSQL...
В первом случае вы, как мне кажется, описываете так называемую EAV модель, или модель Тенцера. Недостатки очевидны - медленные INSERT, UPDATE, DELETE. Необходимость реализовывать самому проверку связей между объектами, интерфейс по управлению свойствами объектов, типов, и т.д. Плюсов тоже не мало, это почти(!) универсально, но не так производительно, как во втором случае. Мне кажется тут надо смотреть, для чего конкретно разрабатывается БД.
Я же привел пример — разработка системы, подобной Хабрахабру.
при разработке конкретного проекта конечно предпочтительней второй вариант, реализация проще и скорость выше. первый больше подходит при разработке универсальной платформы
Спасибо. Я сам пришел к похожему умозаключению.
А затем появятся объекты, которые как и туда и сюда подходят. Грубо говоря были Новости и Статьи, к ним добавили Анонсы - куда их - в отдельную таблицу?
Затем придут теги - и все сущности придется как-то перевязывать между собой, то есть к каждой таблице сущностей добавится еще таблица-связка с тегами.
Теги, комментарии — это настолько обобщенные сущности, что их спокойно можно хранить каждый в одной таблице, привязывая к объектам с помощью идентификатора (objectID) и типа (objectType).
Про «Новости, Статьи, Анонсы» — детальная схожесть этих трех объектов взывает к хранению их в одной таблице, с разными типами (поле type).
А как быть со внешними ключами в этой схеме?
А что если внешним ключом назначить связку objectType и objectID?
Не очень понял как это можно сделать. Колонка должна ссылаться на колонку в другой таблице. Можно ли ссылаться сразу на несколько таблиц?
Не, не может, насколько я знаю. Потому единственный вариант, что могу предложить: таблицу ObjectUniqueIds и ссылки на нее из всех таблиц, к которым можно привязать теги и комменты. Тогда внешний ключ реализуется в два этапа: ObjectID -> ObjectUniqueID -> Comments|Tags. Но тут, конечно придется генерить UniqueID вручную (триггером).

Кстати, msSQL есть такая штука как UID - тип данных такой. Он ваще уникальный.
Еще одна связка? Чем сложнее, тем медленне это все будет работать.
А вот вариант с UID - очень интересен.
Тоже самое можно сделать, например, в постгрес - создав общую последовательность для всех таблиц.
Первый вариант похож на систему, расчитанную под будующую (считаем неизвестную на момент разработки) сильную кастомизацию. Один из таких известнейших продуктов - 1С.

http://www.oracle.com/global/ru/oramag/august2004/russia_gen_abramov.htm

В статье дано описание Remedy, это не суть важно, легко можно подставить туда и "пункт 1".
Я знаю третий. Как только кармы хватит напишу статью по этому поводу.
Поднял карму. Можете написать в личный блог.
Спасибо :) Попробую до футбола выделить время на статью. Моя(?) идея как раз для социальных подходит лучше всего.
Пишите, очень интересно.
Сорри за оффтоп, но: а хабракармаэффект уже не работает? Раньше за просьбы кармы жестоко расплачивались.
ОФФТОП: Я думаю, если человек просит на дело - статью по интересующей тебя теме, то ничего плохого в этом не вижу. От этого только все выиграют.
Прошу прощения, я тут новенький :)
Статья готова http://rvk.habrahabr.ru/blog/45259.html
Надеюсь достойная плата за карму.
1 вариант использутся при гибкой по своей природе структуре таблиц
За второй вариант вас зато никогда не побьют последующие разработчики
Можно предложить еще "третий" вариант: настройщик описывает сущности и связи в какой-либо нотации, а программа затем "умно" генерирует объекты БД (таблицы, хранимки...)по второму варианту.
Выйдет очередной конструктор а-ля 1С :)
По сути отдать проектирование системы на откуп роботу? :)
Все это объединено дисциплиной ORM (Object-Relational Mapping) и хорошо описано на разных ресурсах. Способов представления объектов немного больше чем 2. Вот, например, есть такая статья: http://www.agiledata.org/essays/mappingObjects.html
в ActiveRecord (RoR) эти свзянности уже давно сформулированы (также как и в LIMB-фреймворке, предлагающем свой вариант ActiveRecord)

has_one - связанность один объект к одному
belongs_to - то же самое, но с foreign_key
has_many - множество к одному
has_many_and_belongs_to - один к множеству через дополнительную мета-таблицу
НЛО прилетело и опубликовало эту надпись здесь
Для хранение объектов с похожей структурой годится наследование, в котором основная таблица
содержит общие для всех атрибуты, такие как id, pub_date, mod_date, author_id ...., а
остальные таблица наследуя ее, добавляют свои атрибуты. При этом можно использовать поиск как
по отдельным таблицам, так и по всем (спрашивая мастер таблицу). В PostgreSQL это реализуется
весьма просто. Есть еще способ в PostgreSQL - иметь одну таблицу с общими атрибутами, а всю
специфику вынести в отдельное поле типа перлового хэша.
Да, структура получается очень гибкой, но есть проблема в обработке. Комфортно с ней можно работать только из Perl-а. Когда система развивается, возникает большая потребность в интеграции с другими компонентами, которые могут быть написаны на других языках. И вот там распарсивание хеша может стать проблемой, приходится лепить костыли: парсить руками, либо писать специальные хранимые процедуры для вытаскивания определенных полей хеша.
Я бы предложил хранение в виде XML (благо постгрес нормально с ним работает).

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

Минусы:
- производительность
Почему только из перла ? В PostgreSQL можно работать c SQL, если пользовать наше расширение hstore (http://www.sai.msu.su/~megera/wiki/Hstor…)
Интересная вещь. Спасибо!
Как производительность? Индексируемость?
Для хранения объектов с множеством (от одного до сотни и далее) свойств еще выгодно использовать мета-таблицы.

Например есть сущность User, есть сущности UserGroup, UserAccess etc. В основной табллице хранится главная информация - login, password, created_at и т.д., и связи с правами и группой. В мета-таблице - UserMeta - хранятся свойства объекта в виде ключ-значение: что то вроде (id, user_id, property, value).

Тогда при выборке свойств объекта будут два запроса - первым этамом выборка информации из главной таблицы и связанных таблиц; вторым этапом выборка мета-свойств объекта.

Кто еще применяет такую же архитектуру? Знаю что в WordPress используется такая же идея (свзянность между posts и posts_meta).
* первым этамом - первым этапом

поднимите карму, напишу подробнее как такая же схема используется в classifieds движках (движках объявлений)
Сейчас должно хватать для личного блога.
Если очень много изменяющихся свойств(меняется струткура ) - выделяют ядро сущности, которое хранится в обычных полях. Все поля, которые могут меняться, загоняют в поле xml. эти свойства вторичны и запросы по ним не выполняются или выполняются очень редко, все активные действия выполняяются над полями ядра. Раньше использовалось clob и udf, которые парсили это поле, с появлением xml все делается гораздо проще и быстрее, стандартными средствами.

Наследование в рсубд практически не используется. Нафига, база должна хранить данные, остальным займется приложение.
> Раньше использовалось clob и udf, которые парсили это поле, с появлением xml все делается гораздо проще и быстрее, стандартными средствами.
Ну xml в крайнем случае можно закешировать.

> Наследование в рсубд практически не используется. Нафига, база должна хранить данные, остальным займется приложение.
Согласен, база должна хранить данные, а не модель (модель строится на основе этих данных + поведении). Маппингом данных и сущностей занимается ORM.

Насчет выделения какого-то ядра у сущности - несколько туманная идея... можете привести примеры?
Каковы плюсы от проектировать БД на основе частоты изменения полей?
>Насчет выделения какого-то ядра у сущности - несколько туманная идея... можете >привести примеры?
>Каковы плюсы от проектировать БД на основе частоты изменения полей?
Я приводил решение для случая когда у сущности много изменяющихся полей. Например у кредитной истории могут появляться дополнительные атрибуты необходимые для каких-то скоринговых целей. Основные атрибуты КИ( субъект, документы, адрес, данные бюро) уже определены и не меняются. Просто все поля, которые планируются в будущем видоизменть или добавлять, добавляются в структуру xml. В результате никаких мета-таблиц не надо создавать, определяете схему документа и вперед. Так удобнее. Во первых у старые версии сущности не будут обрастать не используемыми полями, функционалом. И контроль версий естественно лучше. Программа может спокойно парсить сущность по старой xsd, а новые записи по новой. И все это хранится в одной таблице, где количество колонок фикисровано. По произовдительности я думаю даже выигрыш будет против многослойных джойнов.
НЛО прилетело и опубликовало эту надпись здесь
Работали над проектом автоматизации финансового блока компании.
Архитектором выбрал первый вариант, в связи с планировавшейся большой универсальностью и подключением большого числа модулей других подразделений компании.
В итоге все это вылилось в огромный геморрой при работе с данными и пришлось все упрощать и отпиливать напильником в сторону второго варианта.
НЛО прилетело и опубликовало эту надпись здесь
Хочу прокомментировать первый вариант - сейчас на работе с ним приходиться иметь дело...

Описание данной схемы неполно... В нашем случае ObjectsFields является не отдельной таблицей, а целым набором таблиц, для разных типов данных своя таблица. Т.е. существуют таблицы ObjectFieldsVarchar, ObjectFieldsDate, ObjectFieldsBlob и так далее... Понятно, что можно сделать одну таблицу ObjectsFields, в которой будут поля всех типов, но в итоге это совсем не намного изменит ситуацию - работать с этой пачкой сложно.

Присоединюсь ко всем здесь высказывавшимся - работать с этой пачкой говна очень сложно. Либо полностью через хранимые процедуры (которые возвращают тебе строку с полями, которые ты запросил), либо приходится делать УЖАСНЫЕ извращения на клиенте. В частности ужасной ужастностью здесь является известная N+1 проблема, из-за которой динамическая lazy-линковка практически невозможно.
1. Это архитектурный паттерн БД EAV (Entity-Attributes-Values).
2. Это архитектурный паттерн БД Entities and External Domains (название моё, модель по-умолчанию для большинства учебных и малых схем).

Есть ещё:
3. Core Entities & Hiers (Ключевые сущности и наследники, очень мне нравится в последнее время).
4. DW (Facts & Dimensions) — классика аналитических систем.
5. Регистры — хорошее решение для учётных систем.

Кое-какие детали есть здесь: http://DatabaseDesignPatterns.org/index.…
Спасибо за информацию. Хоть что-то полезное нашлось.
первый вариант удобно использовать для мелочей, типа «Просмотры», «Рейтинг».
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации