2009-11-01

Потерянная семантика

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

Потерянная "сила" и другие атрибуты связей. Как в реляционных СУБД, так и в языках программирования, понятие ссылки сводится к идентификации и не позволяет добавлять дополнительные атрибуты связей. Однако, на практике часто бывает полезно учитывать силу, давность или стойкость связи между объектами. Атрибуты связей можно разделить на параметры и классифицирующие атрибуты связей, но и те и другие очень просто моделируются средствами реляционных СУБД, декларативными языками описания как XML, JSON, CLEAR, или активными языками программирования. Главное, не забыть, о том, что ссылки не равносильны, структурно сложны и не могут быть сведены к простым указателям. Есть и исключения, например, во многих СУБД можно определить операции Cascade, Restrict, Update для связей между сущностными, но эти операции описывают не атрибуты, а действия и не могут быть условными или содержать формулы, вложенные запросы, динамические вычисления или алгоритмы. Они хороши только для самых простых случаев, а как только появляется условие, то потерянную семантику приходится реализовывать в виде хранимых процедур и триггеров.

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

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

Потерянный источник. СУБД не предоставляет возможности записывать источник получения данных в полях таблиц. А ведь данные могут быть взяты из импорта, введены вручную, получены из внешней системы и т.д. Приходится выходить из положения добавляя поле, описывающее источник данных другого поля. Реряционная модель не предусматривает формально указать, что одно поле является атрибутом другого поля. Задача "понимания" этой логики ложится на приложение. Чтобы упростить операции можно применять суффиксы и префиксы в именовании полей, например поле Frequency содержит значение частоты, FrequencySource - указывает на источник данных (пользовательский ввод, автоматическая оцефровка, импорт и т.д.), а FrequencyUser - пользователя, отредактировавшего поле вручную или NULL, если значение было получено не от пользователя.

Потерянное время и история изменения данных. Аналогичным образом, как в описанном выше примере может храниться и время фиксации измеренной величины (например FrequencyTime). Однако, часто может быть необходимо хранить одно или несколько предыдущих значений, если одно то можно добавить поле (FrequencyPrevious), а если нам нужна история, то нужна отдельная таблица, и вот логика уже определяется приложением, т.е. на уровне СУБД невозможно задать что таблица хранит историю параметра. Главное, обеспечить целостность данных при декомпозиции, т.е. удалять историю при удалении сущности, атрибут которой имеет историю и слудить за очисткой устаревших не нужных записей.


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

Потерянные группировки. Теряется так семантика группировых связей, когда несколько связей описывают обно физическое явление, а инструментов для объединения связей в группы нет. Сложности есть в формальном описании сложных свойств, когда свойство распадается на несколько полей, а описать их группировку или определить ее мы не можем. В таких случаях нам нужно использовать метаданные, которые будут интерпретированы в сервере приложений или в клиенте. Метаданные можно хранить в именах полей, в именах таблиц, в именах индексов или комментариях к ним (но не все СУБД поддерживают комментарии или дают возможность программно причитать комментарии).

Итак, все приведенные выше случаи говорят нам о сложностях, которые решаются введением метаданных, но если в активных языках (в частности в объектно-ориантированных) у нас развязаны руки для моделирования метаданных, то в СУБД нам часто их просто некуда поместить и приходится выдумывать нестандартные решения. Хотя на практике, в каждом конкретном случае задачу всегда удается решить, но общего решения пока нет.