Точка зрения на ОРСУБД

Статья посвящена прежде всего логическому представлению объектов в базе данных посредством двух объектно-реляционных языков: SQL3 (или SQL:1999) и Zigzag. Реально SQL3 не является окончательным и не поддерживается полностью всеми известными объектно-реляционными системами управления базами данных. Речь в статье идет об объектно-ориентированном языке SQL систем Oracle и Informix. Zigzag отличается от SQL не только в синтаксисе, но также и в механизмах обработки данных. Также следует иметь в виду, что SQL — язык исчисления, Zigzag — язык объектно-реляционной алгебры.

Чтобы определить Объектно-Реляционную Систему Управления Базами Данных (ОРСУБД), достаточно воспользоваться простым уравнением: ОРСУБД = ОСУБД + РСУБД = (O + Р) * СУ * БД. На логическом уровне ОРСУБД есть методы обработки СУ, применяемые к структуре данных БД, которая характеризуется понятиями О (объектная) и Р (реляционная).

Все необходимое для объектного представления доступно в объектной СУБД (ОСУБД). Обычно ОСУБД приравнивают к OОСУБД, а именно к СУБД интегрированной с Объектно-Ориентированным (OO) языком программирования как C++ и Java. Характерные свойства OОСУБД:
1) комплексные данные;
2) наследование типа;
3) объектное поведение.

Комплексные данные могут быть реализованы через постоянные объекты (persistent objects) и XML. OO языки программирования с их определением класса формируют наследование и объектное поведение.
Реляционный концепт в контексте СУБД определен реляционной моделью доктора Е. F. Codd, которая базируется на отношениях в форме двумерных таблиц рядов и столбцов. Преобразование запросов к реляционной алгебре — основное подтверждение относящее базу данных к реляционной модели. Это предубеждение думать, что язык SQL2 — единственный и необходимый критерий РСУБД, точно так же, как думать, что Java — единственный язык ОО-программирования. Примечательная особенность РСУБД — возможность обрабатывать быстро большую массу однотипных n-элементных кортежей (рядов или записей).

комплексные данные

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

Есть много ситуаций, связанных со сложными и непредсказуемыми данными, когда точное описание схемы не требуется или необоснованно замедляет разработку проекта. Кроме того, обе перечисленные причины предопределения схемы в настоящее время не существуют: контроль над входными данными должен осуществляться через поддержку входной формы, например через Javascript на стороне клиента Сети; влияние ограничения типа данных на скорость выполнения работы приближается к нулю с усовершенствованием технического оснащения современных систем баз данных.
Создание комплексных данных в большинстве существующих SQL ОРСУБД основано на предварительном определении схемы через определяемый пользователем тип (UDT, User-Defined Type). Таблица остается самой наглядной формой представления комплексных данных в любой ОРСУБД.

students
 
idnamecourse
firstlast
st031JaneHunterEconomy Planning
st072RichardWhiteComputers in Engineering

Особенности приведенной выше таблицы следующие: атрибут (или поле, или столбец) "name" состоит из "first" и "last" атрибутов; Одним из значений атрибута "course" является множество из элементов "Economy" и "Planning". Такая структура возможна, например, для IBM Informix SQL.

CREATE ROW TYPE Student (
id CHAR(5),
name ROW (first VARCHAR(12), last VARCHAR(20)),
course SET (VARCHAR(128) NOT NULL)
);
CREATE TABLE students OF TYPE Student;
INSERT INTO students
VALUES (
'st031',
ROW('Jane', 'Hunter'),
SET('Economy', 'Planning')
);
INSERT INTO students
VALUES (
'st072',
ROW('Richard', 'White'),
SET('Computers in Engineering')
);

Другие SQL ОРСУБД предлагают другие конструкторы составных типов, например VARRAY или ARRAY вместо SET, и OBJECT вместо ROW. Конструкторы простых встроенных типов с ограничениями как CHAR(5) унаследованы от SQL2. Zigzag принимает вышеупомянутую таблицу без использования конструкторов типов, как ниже, через процедуру readTable. Первая строка входных данных объявляет названия атрибутов. Имя "id" может быть опущено, а "student" обозначать и первичный ключевой атрибут и таблицу.

$readTable() <
student; name:first; name:last; course
st031 ; Jane ; Hunter ; Economy, Planning
st072 ; Richard ; White ; Computers in Engineering
>;

наследование типа

Иерархия структурных комплексных данных предлагает дополнительное свойство, наследование типа. То есть структурный тип может иметь подтипы, которые используют все его атрибуты и содержат дополнительные атрибуты, специфицированные в подтипе. Рассмотрим следующие данные:

employees
 

NameSalary
Sylvia Karsen30000.00

programmers

NameSalaryLanguageProject
William Helprin40000.00C++Seestorm

representatives

NameSalaryRegion
Akiko Yokomoto50000.00Asia

Типы данных формируют иерархию, изображенную ниже.

Employee(Name,Salary)
/ \
Programmer(Language,Project) Representative(Region)

SQL-представление

Для создания базы данных воспользуемся преимуществами Oracle SQL.

CREATE TYPE Employee AS OBJECT (
Name VARCHAR2(20),
Salary NUMBER(6,2)
) NOT FINAL;
CREATE TYPE Programmer UNDER Employee (
Language VARCHAR2(12),
Project VARCHAR2(30)
);
CREATE TYPE Representative UNDER Employee (
Region VARCHAR2(30)
);
CREATE TABLE employees OF Employee;
CREATE TABLE programmers OF Programmer;
CREATE TABLE representatives OF Representative;
INSERT INTO employees
VALUES (Employee('Sylvia Karsen', 30000.00));
INSERT INTO programmers
VALUES (Programmer('William Helprin', 40000.00, 'C++', 'Seestorm'));
INSERT INTO representatives
VALUES (Representative('Akiko Yokomoto', 50000.00, 'Asia'));


Подтипы "Programmer" и "Representative" наследуют все атрибуты от супертипа "Employee". Запрос об объектах "employees" типа "Employee" означает также запрос об объектах подтипов, а именно "programmers" и "representatives".

SELECT e.Name
FROM employees e;

Результатом SQL запроса будет:

Name
--------------------
Sylvia Karsen
William Helprin
Akiko Yokomoto

Zigzag-представление

Та же иерархия данных может быть выражена в Zigzag. Отдельное определение типов не требуется.

$readTable() <
Employee; Name ; Salary
# ; Sylvia Karsen; 30000.00
>;
$readTable() <
Employee:Programmer; Name ; Salary ; Language; Project
# ; William Helprin; 40000.00; C++ ; Seestorm
>;
$readTable() <
Employee:Representative; Name ; Salary ; Region
# ; Akiko Yokomoto; 50000.00; Asia
>;

Zigzag запрос об объектах типа "Employee" означает также запрос об объектах имеющих тип "Programmer" и "Representative". Чтобы получить тот же самый результат, как ранее в SQL, воспользуемся следующим запросом:

= Name:(Employee:);

Отличительное свойство Zigzag — то, что тип действительно является объектом, который определяет класс (в смысле множества) других объектов. Другими словами, типы в Zigzag – также данные. Кроме того, наследование типа означает не только наследование имен атрибутов, но также и наследование значений атрибутов. Например, предположим, что все программисты расположены в одном отделе "E". В случае SQL3 требуется вставить значение "E" во все строки таблицы "programmers". Относительно Zigzag, мы можем быть удовлетворены, если установим "E" только для объекта "Programmer".

$readTable() <
Employee ; Department
Programmer; E
>;

Чтобы проверить наследование значения "E", введем следующий Zigzag-запрос, переводимый как "имена работников отдела Е".

= Name:(Employee:(Department:E));

Результат будет такой:

Name:William Helprin

объектное поведение

Чтобы дать разработчику максимальные возможности, СУБД должна обеспечить некоторую связь (например, ODBC) внешнего языка программирования с внутренним языком СУБД. Дополнительным преимуществом, преобразовывающим (Р)СУБД в О(Р)СУБД, является доступ из внутреннего языка СУБД к программным объектам, а именно к объектам внешнего/внутреннего языка объектно-ориентированного программирования (ООП). Такие программные объекты должны быть сохраняемыми и переносимыми для обработки в базе данных, поэтому они называются обычно как постоянно существующие (или долговременные) объекты. Внутри базы данных все отношения с постоянным программным объектом есть отношения с его объектным идентификатором (OID). Отображение внешних постоянных программных объектов в базе данных — не проблема (смотрите, например, JDO-инструмент http://www.exadel.com/products_jdoproducts.htm или другие http://www.service-architecture.com/object-ori ented-databases/index.html).
Реальный объект можно описать через традиционный элемент базы данных, запись или поле. Это будет ограниченный объект данных (или объект базы данных). Ранее описанные комплексные элементы данных — также объекты данных. Чем отличается программный объект? Каждый программный объект формально может быть определен как образец (или экземпляр), полученный из отображения типа:

тип = { атрибуты, методы } ↓ ОБЪЕКТ = образец = { состояние, поведение }
Наиболее значительным в этом определении, приближающим программный объект к реальному, является то, что тип объекта включает не только атрибуты, но также и методы, отображаемые в поведение объекта. Некоторые ОРСУБД, подобно Oracle и DB2, дают возможность поместить методы внутри определения типа данных. Это позволяет разработать SQL-приложение, подобное приложению ООП-языка (и ОСУБД). Метод, собственно, есть функция или процедура, определенная для некоторого класса объектов. Вызов метода может быть представлен как:

object.method(parameters) = function(object,parameters);

или

object.method(parameters) = procedure(object,parameters);

Левые выражения позволяют воспринять метод как составляющую, которая может быть выражена через объекты. Рассмотрим свойства, связанные с методом и реализованные в ООП-языках. Известно, что поведение объекта (а значит и метод), обозначенное одним названием, может отличаться в соответствии с типом объекта или ситуации (параметров). ООП-языки учитывают это как принцип полиморфизма, который кратко описывается через выражение "один интерфейс, много обеспечений". Другие принципы ООП — наследование и инкапсуляция — связаны как с методами, так и с атрибутами. Наследование было уже рассмотрено. Принцип инкапсуляции в ОРСУБД имеет иной оттенок. Даже продвинутые Oracle 9i и IBM DB2 V8 не учитывают степень инкапсуляции через PUBLIC, PRIVATE и PROTECTED как Java или С++. Инкапсуляция в ОРСУБД сводится к замене атрибута на метод, то есть к использованию виртуальных атрибутов. Например, вместо атрибута price может быть использован метод getPrice(). В последующем обсуждении принципы ООП демонстрируются через Oracle SQL и Java/Zigzag.

SQL представление

Ниже, SQL-пример создает таблицу "equipments" абстрактного типа "Equipment". Реально строка таблицы "equipments" может быть объектом либо подтипа "Platform" либо "Engine". Каждый подтип определяет уникальный getPrice() метод.

CREATE TYPE Equipment AS OBJECT (
name VARCHAR2(24),
NOT INSTANTIABLE MEMBER FUNCTION getPrice() RETURN NUMBER
) NOT INSTANTIABLE NOT FINAL;
CREATE TYPE Platform UNDER Equipment (
size NUMBER,
OVERRIDING MEMBER FUNCTION getPrice() RETURN NUMBER
);
CREATE TYPE BODY Platform AS
MEMBER FUNCTION getPrice() IS
BEGIN
RETURN size * 6
END getPrice;
END;
CREATE TYPE Engine UNDER Equipment (
power NUMBER,
OVERRIDING MEMBER FUNCTION getPrice() RETURN NUMBER
);
CREATE TYPE BODY Engine AS
MEMBER FUNCTION getPrice() IS
BEGIN
RETURN 40 + power * 5
END getPrice;
END;

CREATE TABLE equipments OF Equipment;
INSERT INTO equipments
VALUES (Platform('Tower X04', 4));
INSERT INTO equipments
VALUES (Engine('Ford U14', 14));
SELECT name, getPrice() price
FROM equipments;

Результат:

name price
-------------------
Tower X04 24
Ford U14 110

Java/Zigzag представление

Давайте обратимся к Zigzag. Свободная реализация этого языка основана на Java и дополняет Java.Итак, нужно создать постоянный объект Java в Zigzag-базе данных и получать его атрибуты или вызывать методы через Zigzag . Типы объекта описываются в Java через следующие классы:

public abstract class Equipment implements java.io.Serializable {
public String name;
public abstract int getPrice();
}//Equipment

public class Platform extends Equipment {
public int size;
public Platform(String name, int size) {
this.name = name;
this.size = size;
}//Platform
public int getPrice() {
return size * 6;
}//getPrice
}//Platform

public class Engine extends Equipment {
public int power;
public Engine(String name, int power) {
this.name = name;
this.power = power;
}//Engine
public int getPrice() {
return 40 + power * 5;
}//getPrice
}//Engine

Затем следующий Zigzag-фрагмент создает программные объекты типа "Platform" и "Engine", отображает их содержимое в базе данных через $mapState, и печатает таблицу с атрибутами "name" и "price" как предыдущий SQL-пример.

equipment:[
@po Platform.(Tower X04, 4),
@po Engine.(Ford U14, 14)
];
$mapState(equipment:);
$printTable(equipment:, name, price);

Дополнительно Zigzag обладает уникальной возможностью задавать не только программные объекты, но их атрибуты и методы как множество. То есть метод или атрибут может быть выражен нечетко, через выражение-запрос:
[object expression].[method expression]() — вызов метода программного объекта,
[ object expression].[attribute expression] — обращение к атрибуту программного объекта.

заключение

Трех основных качеств — 1) комплексные данные, 2) наследование типа и 3) объектное поведение — достаточно, чтобы классифицировать РСУБД или СУБД как ОРСУБД или ОСУБД соответственно.
Внутренний язык СУБД как SQL или Zigzag — не критерий, а только материал для классификации на логическом уровне. Язык Zigzag соотносится с объектным SQL, по крайней мере, в объектно-ориентированном представлении данных. Zigzag — более выразителен и помогает работать со структурно более гибкими данными. Однако SQL с его схематизацией типа позволяет устанавливать более строгий контроль однородных данных. Основное отличие проявляется в том, что Zigzag может видеть тип как объект данных и объект данных как тип для других объектов. Это позволяет создать иерархию данных, не только иерархию типа, семантически более точно, например:

продукция(оборудование) / \ печатная видео (оборудование:типография,периодичность) (оборудование:видеокамера,...) / \ | \ журнал книга (периодичность: регулярно,...) (периодичность:нерегулярно,назначение) / | / | \ беллетристика учебник ... (назначение:развлечение) (назначение:образование)

Объект книга наследует не только факт, что это — продукция, характеризующаяся оборудованием и периодичностью, но факт, что оборудование — типография. Кроме того, книга есть тип для объектов: беллетристика, учебник и других, которые наследуют атрибут назначение и периодичность со значением нерегулярно. Если предположить, что образцы книги (беллетристика, учебник, ...) исследуемые целевые объекты, наследование в SQL3 представляется следующей иерархией типа:

продукция(ид,оборудование) / \ печатная(периодичность) видео(...)
/ \ / \
журнал(...) книга(назначение)


Объекты "книга", сохраненные в таблице "книги", будут представлены с соответствующим порядком атрибутов:

книги = [
книга('беллетристика', 'типография', 'нерегулярно', 'развлечение'),
книга('учебник', 'типография', 'нерегулярно', 'образование')
]

Как может быть замечено, значения атрибутов не наследуются, так что "типография" и "нерегулярно" повторены в каждом объекте. Есть уверенность, что следующие версии SQL решат эту проблему: тип будет содержать статический атрибут со значением, подобно статическому полю в Java (статические методы уже существуют в SQL у Oracle и DB2). Такой статический атрибут должен быть полезен в запросе, выбирающем все объекты типов имеющих нужное значение.
В будущем SQL должен владеть менее выразительными, чем Zigzag, но разумно простыми конструкциями, чтобы рассматривать типы в роли объектов. Гибкость, основанная на рассмотрении объектов в качестве типов, останется прерогативой таких языков, как Zigzag. Чтобы создать объекты типа "учебник" и "беллетристика", SQL3-разработчик создаст новые типы и новые таблицы или, что лучше, преобразует существующую таблицу в новые. Zigzag-разработчик использует объекты "учебник" и "беллетристика" как уже существующие типы. Например, чтобы добавить объект "физика" он может ограничить себя составлением только одной инструкции, подобной :учебник:физика(...).

Сергей Савушкин



Сетевые решения. Статья была опубликована в номере 08 за 2003 год в рубрике мнение

©1999-2024 Сетевые решения