Еще вчера господствующей технологией в области баз данных была сравнительно простая, имеющая строгое математическое обоснование реляционная технология. Существенный прогресс в ИТ внес свои коррективы и сегодня технология работы с базами данных должна быть удобной и динамичной, возможно, в ущерб математической простоте и логической строгости. Изменение требований привело к попыткам создания объектно-ориентированных баз данных, перспективы завершения работ над которыми вызывают серьезные сомнения — на пороге появился XML.

В статье [1] мы уже сравнивали язык XML с реляционным языком, обращая внимание на два следующих важных момента. Во-первых, XML — язык описания данных произвольного документа, а реляционный язык таковым не является. Это принципиально потому, что представление данных как документа является для человека естественным представлением, а представление в виде таблиц — искусственным. Реляционная таблица, в лучшем случае, есть отдельный фрагмент документа. Во-вторых, любые реляционные данные могут быть непосредственно отображены в XML, но не наоборот. Действительно:

  • XML поддерживает упорядоченное хранение данных, а реляционное представление нет. Например, с реляционной точки зрения выражения или тождественны.
  • Связи между реляционными таблицами могут быть только на уровне записей, но не на уровне значений. Например, для тега a1 нужна отдельная таблица.
  • Запись в реляционной таблице не может содержать нескольких значений для одного реквизита. Например, тег A не может быть представлен реквизитом (требуется таблица), но это нарушит однородность тегов A и B: a1a2 b1 .

Для того чтобы сказанное не осталось для менее искушенного читателя голой абстракцией, проследим, к чему это приводит. Рассмотрим некий документ с входящим номером 51, который представлен в виде XML следующим образом:

<Документ Номер="51"
Тип="Предложение">
<Содержание>Мы, ваши
сотрудники
<Автор>Иванов Иван
<Автор>Петрова Мария
<Содержание>предлагаем Вам …

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

Для того чтобы мы могли автоматически воссоздать документ в своем первоначальном виде, необходимо сохранить в базе данных порядок следования значений реквизитов. Для этого в таблицы 2 и 3 добавлен служебный реквизит «Позиция». Сделанное преобразование семантически полное, «реляционно-безупречное» и очень неудобное для использования. Попробуем подойти несколько иначе — уберем таблицу 3, а вместо служебного реквизита «Позиция» сделаем в таблице 1 реквизит «ПолныйТекст» (рис. 2).

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

  • В предыдущем варианте часто встречающийся бюрократический штамп «Мы, Ваши сотрудники» был значением реквизита, соответственно он мог быть индексирован и по нему пользователь мог выполнять выборку в базе данных определенного типа документов, а теперь нет.
  • База данных приобрела так называемую «вредную избыточность» по реквизиту «Автор». Если «Петрова» сменит фамилию на «Сидорова» и надо будет откорректировать соответствующие записи в базе, то вас ждет большая работа — фамилии в значениях реквизита «ПолныйТекст» придется менять «вручную».

Дальнейшее «улучшение» структуры базы данных можно сделать, если ликвидировать таблицу 2, а вместо нее в таблице 1 создать реквизит «Автор» и записать в его единственное значение сразу обоих авторов (рис. 3).

Теперь мы получаем более тонкий, но не менее неприятный недостаток, связанный с типом данных. По здравому смыслу реквизит «Автор» относился раньше к типу данных — «упорядоченный список из двух элементов»: первый элемент — фамилия, второй — имя. Теперь он, наверное, просто текст, со всеми вытекающими отсюда последствиями, связанными с индексацией и поиском. В конце концов, можно вообще убрать реквизит «Автор» и перейти к неструктурированному хранению содержимого документа только в виде реквизита «ПолныйТекст», но при этом сама база теряет смысл как таковая. К сожалению, в современных реляционных базах данных при хранении подобных документов часто именно такая картина и наблюдается.

Объектные модели реляционных и объектно-ориентированных СУБД

С первого взгляда объектно-ориентированные СУБД можно принять за простой результат объектного описания реляционной модели данных. Действительно, реляционная таблица — это класс, имена реквизитов — имена свойств, записи — объекты (экземпляры класса), значения — значения свойств объекта. Сколько таблиц в базе, столько и классов, сколько записей в таблице — столько и объектов данного класса. Домены — специальные классы, из которых обычные классы для каждого своего свойства могут наследовать методы, проверяющие принадлежность значения свойства домену и определяющие их манипуляционные возможности. Временные таблицы, получающиеся в результате манипулирования — временные классы, а их записи — виртуальные объекты. Однако при более внимательном рассмотрении обнаруживается, что применение объектного подхода к реляционной модели вносит одно принципиальное изменение в модель данных, связанное с расширением типов данных [2]. Именно здесь и лежит четкая грань между объектным описанием реляционной модели данных и моделью данных объектно-ориентированных СУБД. Речь идет не о расширении используемых типов данных вообще (реляционная модель это допускает безотносительно к объектному подходу), а о расширении специфическом — возможности определения внутри класса свойства, одноименного с некоторым другим классом, значениями которого были бы неупорядоченные множества ссылок на идентификаторы объектов этого другого класса.

Этот вопрос тесно связан с вопросом о способе описания связей между таблицами или классами. Такая сущность как «связь» принципиально отсутствует в реляционной модели по причине ее логической избыточности [3]. Вместо нее используются понятия «первичный ключ» и «ссылочный ключ», не отягощающие логику реляционной алгебры дополнительными построениями. Причем ссылочный ключ находится в дочерней таблице и ссылается на первичный ключ, находящийся в родительской таблице.

Вернемся к нашему примеру (рис. 1) — таблица 1 является родительской, таблицы 2 и 3 по отношению к ней дочерними. Первичными ключами в таблице 1 являются значения реквизита «Номер», в таблице 2 — «Номер» и «Позиция», в таблице 3 — «Номер» и «Автор». Ссылочными ключами в таблицах 2 и 3 являются значения реквизита «Номер». Объектный подход описывает эти связи совершенно иначе. «Связь», как сущность, также отсутствует, вводятся понятия «Идентификатор» (объекта) и «Ссылка» на этот идентификатор. В отличие от реляционной модели, ссылка находится не в дочернем, а родительском классе, идентификатор же, напротив, в классе дочернем, а не в родительском. Если изобразить этот объектный подход в виде табличек, то получим рис. 4. Ссылочные ключи в классах 2 и 3 уже не нужны и мы их удалили (в рамках объектного подхода ссылочный ключ часто рассматривают как одно или несколько свойств объекта, наследуемых от родительского). Первичные ключи не потеряли своей значимости, поскольку используются не только для организации связей, но и для обеспечения уникальности объектов. В классе 2 «Автор» уникальность объекта определяется не автоматически присваиваемым системой идентификатором, а именно значением свойства «Автор». По смыслу этого примера, двух «Иванов Иван» в одной докладной записке быть не может, даже если у них разные идентификаторы.

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

К достижениям объектно-ориентированной технологии относят также интегрирование поведенческого и структурного аспектов [2]. К этому вопросу нужно относиться с осторожностью — что именно интегрируется и куда. Если речь идет о методах реляционной алгебры (или, если угодно, «объектной алгебры»), то они, очевидно, должны быть общими для всех классов в базе данных, а значит, унаследованы из одного специального системного класса и, разумеется, не инкапсулированы в конкретные классы. Если речь идет о методах логики работы конкретного приложения (бизнес-логики), то их также имеет смысл размещать в конкретном специальном классе, связанном с этим приложением, приложений может быть много и они меняются, а структура базы остается.

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

Объектная модель XML

Объектная модель XML построена существенно иначе [4]. Имеется два основных класса — «XML-документ», каждый из объектов которого описывает какой-либо документ в целом, и «XML-узел», каждый из объектов которого описывает каждый из узлов иерархического дерева этого документа. Несколько упрощая, можно сказать, что класс «XML-узел», не считая идентификатор, имеет пять основных свойств: «Тип», «Имя», «Значение», «Дети» (ссылка на дочерние узлы кроме атрибутов) и «Атрибуты» (ссылка на них как на дочерние узлы).

Свойство «Тип» может принимать целое значение от 1 до 12, на сегодняшний день существует всего 12 типов узлов. Из них мы кратко рассмотрим четыре: 9 — Документ, 1 — Элемент, 2 — Атрибут элемента, 3 — Текст. Из названных типов узлов индивидуальное имя имеют 1 и 2, значением обладают 2 и 3, ссылками на идентификаторы дочерних узлов — 9, 1, 2, ссылками на атрибуты — 1.

В отличие от рассмотренной объектной модели, ссылка на дочерние узлы представляет собой упорядоченный список, который может содержать идентификаторы узлов типа — 1, 2, 3. Свойство «Атрибуты» представляет собой неупорядоченный список атрибутов и содержит идентификаторы узлов типа 2. Если изобразить наш пример в виде таблички, то получим описание класса «XML-узел» (рис. 5).

Отметим любопытный момент — значения узлов с идентификаторами 3 и 4, а также 5 и 6 дублируют друг друга, что говорит о незавершенности объектной модели как таковой (конкретно — не установлена окончательно модельная роль атрибута). Вообще говоря, модель имеет определенную логическую избыточность (например, по количеству типов узлов), обусловленную причинами исторической преемственности, однако избыточность скомпенсирована унификацией представления.

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

Ограниченность набора низкоуровневых операций позволяет представить преобразование одного XML-документа в другой в виде данных — опять же в виде XML-документа. Грубо говоря, бизнес-логика может быть построена как преобразование одних XML-документов в другие при помощи третьих. Описания данных (метаданные) и описания описаний разложены в ту же объектную модель. Таким образом, XML-ориентированная база данных полностью сама себя описывает.

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

Выводы

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

Технологию объектно-ориентированных СУБД можно рассматривать как «пробный шар» в дальнейшем технологическом развитии СУБД по направлению к большей семантике и естественности представления данных. Полученные результаты, в целом, можно рассматривать как отрицательные — уровень затрат на разработку этой технологии не оправдывает получаемых результатов. Большинство существующих СУБД, в том числе и упоминаемая в статье Cache, под рекламным лозунгом «объектно-ориентированные» просто скрывают объектное описание реляционной схемы данных. С учетом экономической ситуации, это говорит о здравомыслии руководителей фирм-разработчиков.

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

Валерий Веселов (valera@sparm.com), Анатолий Долженков — сотрудники предприятия СП-АРМ (Санкт-Петербург).

Литература

[1] Веселов В., Долженков А. XML и технологии баз данных. — «Открытые Системы», 1999, №05-06.

[2] Кузнецов С. Объектно-ориентированные базы данных — основные концепции, организация и управление: краткий обзор. — http://www.citforum.ru/database/articles/index.shtml

[3] Кузнецов С. Анализ вклада Кодда в Великий спор. — там же.

[4] Бумфрей Ф. и др. XML. Новые перспективы WWW. Пер. с англ. — М.:ДМК, 2000. — 688 с.


Конкретный интерфейс объектной модели XML и физического хранения

Как правило, в базе данных для организации физического хранения данных на диске используются либо индексно-последовательные файлы, либо B*-деревья. B*-деревья обеспечивают быстрый доступ к хранимым данным, сортировку данных в момент их записи, сжатие ключей и т.д. Конкретная реализация B*-деревьев — это секрет фирмы-разработчика.

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

InterSystems. В основе структуры ее B*-дерева, также как и в основе синтаксиса XML, лежит иерархия. Это приводит к логическому соответствию интерфейса физического хранения СУБД Cache низкоуровневому интерфейсу объектной модели XML. Можно сказать, что для Cache —  XML-доступ к данным — это просто прямой доступ к данным. В этом смысле Cache можно было бы характеризовать как XML-ориентированную.

Представление B*-деревьев в интерфейсе прямого доступа — это глобал, хранимый на диске рассортированный по строковым индексам массив произвольной размерности вида:

^G(Ind1,Ind2,...,IndN)=Text,

где G — имя глобала, индексы Ind1,Ind2,...,IndN и значение Text — любые строки текста, 1,2,...,N — уровень иерархии индекса, N — произвольно. XML-документ непосредственно отображается в структуру глобала, причем не единственным способом. В простейшем варианте в нечетный индекс попадает тип и имя узла, а в четный —  его позиция в списке других дочерних элементов его родителя:

^G(Name1,Pos1,Name2,Pos2,...,
NameN,PosN)=Value, 

где Name1,...,NameN — тип и имя узла, Pos1,...,PosN — его позиция по порядку, 1,2,...,N — уровень их вложенности, Value — значение узла. Применительно к нашему примеру, глобал может иметь следующий вид:

^DataBase(Документ,51,@Тип)=
Предложение
^DataBase(Документ,51,Содержание,1)
=Мы, Ваши сотрудники
^DataBase(Документ,51,Содержание,4)
=предлагаем Вам...
^DataBase(Документ,51,Автор,2)
=Иванов Иван
^DataBase(Документ,51,Автор,3)
=Петрова Мария

В данном варианте учтено, что теги «Содержание» и «Автор» содержат только текст, причем в виде единственного узла. Если бы, например, «Петрова» и «Мария» представляли собой два разных текстовых узла относящихся к общему родителю «Автор», то вместо последней строки необходимо было бы использовать более полную запись:

^DataBase(Документ,51,Автор,3,#text,1)
=Петрова
^DataBase(Документ,51,Автор,3,#text,2)
=Мария

Индексы глобала, возникшие из атрибутов, помечены первым символом «@», а индексы, возникшие из узлов с фиксированными именами — «#». Атрибут номер удален, поскольку его значение представляет собой уникальный позиционный код тега «Документ».

Для иллюстрации соответствия логики интерфейсов прямого доступа Cache и объектной модели XML приведем простой пример. Откроем базу данных и получим на нее ссылку. Далее возьмем документ 51, найдем его первый дочерний узел, затем следующий за ним и присвоим ему значение «Сидоров Сидор» вместо «Иванов Иван». В варианте XML это будет следующая конструкция:

MyActXObj = new ActiveXObject
(«Microsoft.XMLDOM»);
RefDB = MyActXObj.load
(«database.xml»);
RefDoc = RefDB.selectSingleNode
(«/Документ[@Номер=?51?]»);
RefFirstCh = RefDoc.firstChild;
RefNextSb = RefFirstCh.nextSibling;
RefNextSb.value = «Сидоров Сидор»;

В варианте Cache:

Set RefDB=$Name(^DataBase)
Set RefDoc=$Name(@RefDB@
(«Документ»,51))
Set RefFirstCh=$Name(@RefDoc@
($Order(@RefDoc@(«»))))
Set RefNextSb=$Name(@RefDoc@
($Order(@RefFirstCh)))
Set @RefNextSb=»Сидоров Сидор»