Одна таблица или две?

Модераторы: kdv, CyberMax

SAV
Сообщения: 54
Зарегистрирован: 19 авг 2006, 17:59

Сообщение SAV » 29 авг 2006, 13:59

CyberMax писал(а):Поддержу Merlin'а. Почти с самого начала работы с БД тоже полностью отказался от естественных ключей для ПК и ВК. И серверу проще интеджеры пережевывать, и база наглядней и прочая... В книжках по БД теорию пишут, которая, как известно, от практики отличается.
Ну всё гуру, хватит глумиться,я попробовал,осознал поправил что надо.

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 29 авг 2006, 14:13

Да брось ты. Глумятся над нечитателями доки. Если человек чего не понял - дружески посмеиваются, не без этого. Учти только, что замена естественного композита в ПК-ФК на один искусственный инт вообще-то может быть чревата, если по логике предметной области и реализации интерфейса допустимы апдейты естественных полей связи. Можно, но осторожно и только если одновременный доступ таких функций к связанным записям в разных транзакциях исключён.

CyberMax
Заслуженный разработчик
Сообщения: 638
Зарегистрирован: 31 янв 2006, 09:05

Сообщение CyberMax » 29 авг 2006, 16:20

Merlin писал(а):Учти только, что замена естественного композита в ПК-ФК на один искусственный инт вообще-то может быть чревата, если по логике предметной области и реализации интерфейса допустимы апдейты естественных полей связи.
Поподробней?

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 29 авг 2006, 16:26

чего уж подробней. извечная проблема естественных ключей - если они меняются, все ссылки на такой ключ также должны меняться. то есть каскадный update во всей красе.
а с искуственными ключами каскадный update не нужен, ибо ЕК менять нет смысла, и живет он от insert до delete без изменений.

SAV
Сообщения: 54
Зарегистрирован: 19 авг 2006, 17:59

Сообщение SAV » 29 авг 2006, 17:37

kdv писал(а):чего уж подробней. извечная проблема естественных ключей - если они меняются, все ссылки на такой ключ также должны меняться. то есть каскадный update во всей красе.
а с искуственными ключами каскадный update не нужен, ибо ЕК менять нет смысла, и живет он от insert до delete без изменений.
Это вполне понятно, я учёл это поэтому поправил только то что нужно :-). А тема пока остаётся открытой... Немного переформулирую вопрос: LOG (или история) разных событий. Есть некоторый объект с набором характеритик (состояний),в моём случае это запись в таблице ITEMOBJ... с уникальным ID и другими полями таблицы описывающими этот экземпляр,есть справочник событий (о нем я попозже спрошу :-) ). Есть табличка HISTOBJ.. очень похожая на ITEMOBJ... но с дополнительными полями КТО,КОГДА ЗАЧЕМ,ПОЧЕМУ и ЧТО сделал. Как грамотно сделать лог действий юзера???? Мой вариант: после выполнения какого то действия апдейтить новыми значениями в ITEMOBJ нужные поля и вставлять в HISTOBJ КТО,КОГДА...это действие сделал и какие новые значения он внес. Следственно остальные поля таблицы HISTOBJ... останутся пустыми(NULL),так как размножать все значеия ITEMOBJ в HISTOBJ получится громостко,хотя тоже имеет смысл- можно узнать всё состояние на лубой момент времени.

Есть ли предложения по грамотному ведению истории???

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 29 авг 2006, 18:02

Простейший пример. Транспортная партия (грузовик с товаром)

Код: Выделить всё

Заголовок
ID    Primary
Атрибуты

Товарный состав
ID             Primary
ID_ТП        Foreign Заголовок и первый сегмент Unique
ID_Товара Foreign товары и второй сегмент Unique
Количество


Состав порезервно
(одна товарная позиция для нескольких получателей)

Вариант 1
Трёхсегментный Primary и ФК на товарный состав по Unique
ID_ТП                
ID_Товара
ID_Получателя
Количество

Вариант 2
Двухсегментный Primary и ссылка на товарный состав по Primary
ID_Товарного состава
ID_Получателя
Количество
в варианте 2 сервер не будет сопротивляться изменению ID товара (исправление ошибки регистрации например) без предварительного снятия (возврата на склад) резервов. Что чревато - если в приложении есть ошибки по обслуживанию такой функции, то может получиться так, что резерв в составе ТП будет стоять совсем не на тот товар, который данному покупателю был нужен. Также можно и ошибиться при "ручной" правке данных в аварийных режимах мимо приложения. Так что если такие апдейты полей связи, замещаемых искусственным ключом "для простоты" предполагаются постановкой, то лучше (надёжнее) придерживаться всё-таки более трудоёмкого в писании запросов классического варианта 1.

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

Merlin
Динозавр IB/FB
Сообщения: 1502
Зарегистрирован: 27 окт 2004, 11:44

Сообщение Merlin » 29 авг 2006, 18:31

SAV писал(а): Есть ли предложения по грамотному ведению истории???
Грамотное - это то, которое тебе лично нужно, такшта... А по сути я всё что мог уже сказал.

kdv
Forum Admin
Сообщения: 6595
Зарегистрирован: 25 окт 2004, 18:07

Сообщение kdv » 29 авг 2006, 18:50

можно узнать всё состояние на любой момент времени.
оч. тонкий момент. особенно в смысле "узнать". Например, при изменении реквизитов фирмы что делать со старыми договорами? Для них должны быть старые реквизиты, или новые? История изменений нужна зачем - для оперативных расчетов (типа курс валюты на дату), или просто для логирования действий пользователей?

В обычных системах это разруливается на уровне конкретной сущности или доп-сущности специально для "истории".
У тебя же нечто вроде объектного слоя, как я понял. Здесь может быть туча вариантов - у меня в системе было сделано "версионирование". То есть старый документ мог остаться на своем месте, новые ссылки шли на новый.
Есть решения, когда изменения кидают в xml, и хранят в blob (есть статья на сайте). Но в любом случае мне кажется, что лепить сами изменения в таблицу лога "событий" - нехорошо. Особенно если у разных объектов разные атрибуты (и их число произвольное).

Хорошо пользователям Lotus Notes - там документ имеет GUID, и изменения пишутся только по измененным столбцам. Вот...

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 29 авг 2006, 20:04

Если без версий объектов, то (упрощённо опять же) можно так:

Код: Выделить всё

/* Пользователи */
create table OBJ_USERS(
  ID integer not null primary key,
  Name varchar(100)
);

/* Собственно объекты */
create table OBJECTS(
  ID integer not null primary key,
  Name varchar(100)
);

/* Свойства объектов (может быть разное кол-во) */
create table OBJ_ITEMS(
  ID integer not null primary key,
  ParentID integer not null foreign -> OBJECTS.ID,
  Name varchar(100)
);

/* Справочник событий */
create table OBJ_EVENTS(
  ID integer not null primary key,
/* ParentID тут нужен только в случае если события не "общие" а зависят от объекта */
  ParentID integer not null foreign -> OBJECTS.ID,
  Name varchar(100)
);

/* Собственно история */
create table OBJ_HISTORY(
  DateRec date not null,
  ObjectID integer not null foreign -> OBJECTS.ID,
  EventID integer not null foreign -> OBJ_EVENTS.ID,
  UserID integer not null foreign -> OBJ_USERS.ID
);
Последний раз редактировалось WildSery 01 сен 2006, 13:21, всего редактировалось 1 раз.

SAV
Сообщения: 54
Зарегистрирован: 19 авг 2006, 17:59

Сообщение SAV » 29 авг 2006, 22:49

kdv писал(а): Например, при изменении реквизитов фирмы что делать со старыми договорами? Для них должны быть старые реквизиты, или новые?
Это сложный вопрос, думаю что нужны новые реквизиты,но с другой стороны окажется невозможным поднять старые договора,думаю, что буду делать лог договоров вместе с реквизитами.
kdv писал(а): История изменений нужна зачем - для оперативных расчетов (типа курс валюты на дату), или просто для логирования действий пользователей?
История нужна для сбора статистики,т.е. для логирования действий и входных данных с которыми выполняется действие,при этом результаты(выходные данные) действия можно получить в любой момент взяв сохранённые в истории данные и выполнив над ним действие,которое тоже как известно лежит в логе.
kdv писал(а): У тебя же нечто вроде объектного слоя, как я понял.
В точку :-)
kdv писал(а): у меня в системе было сделано "версионирование". То есть старый документ мог остаться на своем месте, новые ссылки шли на новый.
Есть решения, когда изменения кидают в xml, и хранят в blob (есть статья на сайте). Но в любом случае мне кажется, что лепить сами изменения в таблицу лога "событий" - нехорошо. Особенно если у разных объектов разные атрибуты (и их число произвольное).
"версионирование" есть,как для объектов,так и для действий. А хранение изменнений в BLOB,не очень то удобно для сбора статистики.
WildSeryv писал(а): Если без версий объектов, то (упрощённо опять же) можно так:
Близко... только есть некоторые особенности.Есть экземпляры однотипных объектов включённые в группу.Группа описывается как в программе так и в бд по большей части независимо от других групп (либо с сылками на какие-то состояния экземпляра другой группы), следственно и способ хранения разных групп - в разных таблицах,а вот действия являются общими,т.е. группа имеет только ссылку на ID разрешённых дйствий и "не знает" как это действие повлияет на его состояние...


Если заинтересовало,то могу поподробнее расписать что к чему. Мне было бы инересно узнать про другие реализации ООП+RDBMS.

WildSery
Заслуженный разработчик
Сообщения: 1738
Зарегистрирован: 05 июн 2006, 16:19

Сообщение WildSery » 01 сен 2006, 13:25

Не вижу, как усложнение сруктуры, введение групп и версий может отразится на таблице истории. Её структура не изменится.

Ответить