Интеграция языков программирования с базами данных: в чем состоит проблема?

Автор работы: Пользователь скрыл имя, 23 Сентября 2011 в 22:30, статья

Описание

Проблема «потери соответствия» (impedance mismatch) между языками программирования и системами баз данных обсуждается в сообществе баз данных на протяжении всей моей профессиональной жизни. Попытки решения этой проблемы породили направления языков программирования баз данных, объектно-ориентированных и, отчасти, объектно-реляционных баз данных.

Работа состоит из  1 файл

Интеграция языков программирования с базами данных.doc

— 201.50 Кб (Скачать документ)

Пересылка критериев. В большинстве баз данных обеспечивается автоматическое управление индексами, и выполняется оптимизация запросов на основе детального знания структуры, содержания и расположения данных [21]. Оптимизатор запросов базы данных производит план для всей операции, которую требуется выполнить. При оптимизации запроса учитываются детали выполняемой операции и контекст, в котором она будет выполняться. Контекст включает статистические свойства реальных хранимых данных, объем доступной памяти, загрузку процессора, частоту поступления различных видов запросов и т.д. Для оптимизаций этого вида требуется специальное знание данных и их связей – но эта информация обычно недоступна для компиляторов языков программирования общего назначения.

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

Оказывается также  возможным определить программные  конструкции, которые позволяют  задавать критерии поиска с использованием стандартного синтаксиса булевских  выражений, но выполнять поиска в  виде запроса к базе данных. В расширении Linq языка C# этот метод используется для сборки запросов, посылаемых в базу данных [1810]. Добавляется новая конструкция итерации, похожая на оператор выборки языка SQL, для указания критериев, которые должны обрабатываться в удаленном режиме.

Стандартные конструкции  итерации в AppleScript позволяют специфицировать  критерии поиска в соответствии с объектной моделью удаленного приложения [2]. Результирующие критерии поиска передаются для эффективной обработки в удаленное приложение.

Существующий  синтаксис может использоваться и для выражения запросов. В Safe Query Objects для определения запроса используется обычный булевский метод [17]. Запросы не выполняются в виде стандартного байт-кода, а преобразуются в запросы к базе данных и соответствующий интерфейсный код для вызова CLI базы данных. Поскольку до преобразования запросы подвергаются проверке типов, вызовы CLI не вызывают ошибки типов.

6.2 Оптимизация навигации

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

Упреждающее чтение родственных объектов (P3). В исходном коде на рис. 2 для печати названия отдела, в котором работает служащий, производится переход по связи department. В персистентной объектной системе этот переход приведет к загрузке соответствующего объекта-отдела, если он уже не загружен. Если персистентность поддерживается на основе реляционной базы данных, каждый объект-отдел может загружаться с использованием отдельного запроса, что существенно снижает производительность.

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

При использовании  интерфейса уровня вызова от программиста требуется спецификация данных, производимых запросом, следовательно, программист  отвечает за оптимизацию навигации. В средствах объектно-реляционного отображения поддерживается ограниченная оптимизация навигации. В EJB и JDO можно специфицировать автоматическую загрузку родственных объектов, но в настоящее время это свойство является глобальным, не специализированным для запросов. В Toplink и Hibernate 3 имеется более гибкая поддержка оптимизации навигации, но добавление соответствующих подсказок для загрузки достаточно обременительно, и механизмы не являются полностью универсальными. Например, в Toplink поддерживается загрузка только одного уровня многозначных податрибутов. Оптимизация навигации должна являться целью любого решения проблемы потери соответствия.

Многоуровневая  итерация (P4). Особенно трудным случаем навигации является многоуровневая итерация через многозначные связи. Этот паттерн трудно представляется с использованием текущего варианта SQL. Одним из примеров является многоуровневая итерация, в которой несколько уровней многозначных зависимостей включается в результаты запросов. Такой паттерн иллюстрируется на рис. 5. Даже если коллекции родственных элементов загружаются в одном запросе, запросу требуется загрузить служащих каждого отдела и проекты каждого служащего. Если в Остине имеется отделов, и в каждом отделе в Остине в среднем работают служащих, то потребуется выполнить 1 + nm запросов.

Можно загрузить  требуемые данные за три запроса: один для загрузки отделов в Остине, один для загрузки служащих, работающих в этих отделах, и один для загрузки проектов, в которых участвуют  эти служащие. В каждый из этих запросов должно дублироваться условие из верхней части цикла. Если все результаты должны возвращаться в правильном порядке, то требуется поддерживать вложенный порядок сортировки. Наконец, клиент должен сопоставлять связанные элементы одной таблицы и соответствующие поднаборы во вложенных таблицах. Заметим, что возможен и одиночный запрос, хотя названия отделов и имена служащих будут дублироваться.

for each Department d in DB.getDepartments() sorted by size

    if d.city = ‘Austin’ then

      print( d.name );

for each Employee e in d.employees sorted by e.name

    print( e.name );

for each Project p in e.projects sorted by p.date

    print( p.name );

Рис. 5. Псевдокод для  многоуровневой итерации

Этот стиль  невозможно выразить на SQL, хотя это  можно сделать на языке OQL. При пересмотре SQL следует обращать большее внимание на виды запросов, требуемых для поддержки объектно-реляционного отображения [42]. Если проводить аналогию с разработкой RISC-процессоров, SQL можно рассматривать как разновидность языка ассемблера: вместо того, чтобы разрабатывать понятный, удобный для человеческого восприятия интерфейс, более эффективным оказывается определять распространенные паттерны, генерируемые клиентскими программами, для разработки оптимизированного интерфейса. Проводилось исследование по обнаружению многоуровневой итерации и повышению ее эффективности с использованием упреждающего чтения [25], но ни в одной коммерческой системе этот тип упреждающего чтения не реализован.

6.3 Манипулирование  массивными данными  (P5)

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

for (Employee e in db.allEmployees() )

    if ( e.department.name.equals(“Sales”) )

      e.salary = e.salary * 1.2;

В этом случае применимы  оптимизации, описанные в предыдущем подразделе. Легко использовать явное выполнение запроса для запуска оператора SQL, выполняющего массивную операцию:

UPDATE Employee set salary = salary * 1.2

    FROM Employee INNER JOIN Department d ON d.ID = e.Department

    WHERE d.name = 'Sales'

Но ни средства объектно-реляционного отображения, ни основанные на Java персистентные языки  программирования не допускают эффективного выполнения массивных операций обновления в реляционных базах данных. AppleScript допускает удаленное выполнение операций обновления. В проектах языка DBPL [38] и его приемника Tycoon [35] исследовались оптимизация поиска и массивные операции в среде ортогональной персистентности. В проекте Tycoon предполагалось интегрировать оптимизацию в компиляторе с оптимизацией запросов к базам данных, но никакие окончательные результаты не были опубликованы [22]. Запросы, не ограниченные кодом одного модуля, оптимизировались во время выполнения путем применения динамической компиляции. Ни для DBPL, на для Tycoon не публиковались какие-либо оценки производительности; известно только число строк кода в реализации.

Кэширование. Стратегии кэширования не зависят от особенностей интерфейса между языком и базой данных, по крайней мере, с точки зрения программиста, использующего интерфейс. Конечно, на способы кэширования должны обращать внимание разработчики инфраструктуры доступа к данным и баз данных. Однако в этой статье мы фокусируемся на проектных решениях, затрагивающих пользователейинфраструктуры доступа к данным, а не разработчиков.

7. Повторное использование

В предыдущем разделе  обсуждались вопросы локальной  оптимизации. Кроме того, имеются  аспекты, связанные с композицией  или декомпозицией операций.

Параметризуемые запросы (R1). Параметризуемые и динамические запросы возникают при извлечении запросов из программы для их удаленного выполнения в базе данных. Например, при извлечении запроса из кода с ортогональной персистентностью, показанного на рис. 2, для его явного выполнения в виде SQL-запроса (см. рис. 3) префикс фамилии служащего становится параметром запроса. При явном выполнении запросов трудно специфицировать параметры запросов, и типы параметров не проверяются до времени выполнения.

Динамические  запросы (R2). Динамические запросы – это запросы, которые представляются в виде символьных строк, конструируемых во время выполнения программы. Хотя идея динамических запросов может казаться ужасной, они достаточно распространены, и от них не следует сходу отказываться. Динамические запросы могут обрабатываться путем частичного выполнения запроса на основе данных, которые влияют на запрос, но не зависят от базы данных [17]. Например, если в поисковой форме пользовательского интерфейса допускается указание набора необязательных критериев поиска, то результирующий запрос можно частично вычислить для конкретного набора критериев. Подробное объяснение приводится в [17]. Динамические запросы также возникают при реализации тонких правил авторизации, применяемых индивидуально к каждому пользователю [36]. Мы полагаем, что отсутствие поддержки динамических запросов является основной причиной отказа от большинства форм встраиваемого SQL [27].

Динамические  запросы также требуются для  создания произвольных соединений (ad-hoc joins) в приложениях, поддерживающих оперативную аналитическую обработку (OLAP). Такие приложения в этой статье не обсуждаются.

Модульные запросы (R3). Поскольку в большинстве языков программирования общего назначения имеется поддержка модульной декомпозиции – с использованием функциональной абстракции и абстракции данных, – у соответствующих персистентных языков имеются те же возможности. Хорошо известно, что модульность может мешать оптимизации, но в контексте доступа к базам данных эта проблема может еще более усложниться. И поисковая, и навигационная оптимизация зависят от знания всех условий и данных, участвующих в доступе к персистентным данным. Оптимизация запросов лучше всего работает в тех случаях, когда базе данных поручается выполнение больших частей работы, а не отдельных операций. Тогда сокращается число взаимодействий приложения с базой данных, а оптимизатор получает больший простор для оптимизации. Важно заметить, что, хотя в реляционной алгебре поддерживается модульная композиция, поскольку каждый запрос является отношением, на практике может быть достаточно трудно комбинировать результаты двух SQL-запросов на семантическом уровне. В решении проблемы интеграции языков и баз данных следует поддерживать модульность, композицию и повторное использование структур программ, обрабатывающих большие объемы данных.

Информация о работе Интеграция языков программирования с базами данных: в чем состоит проблема?