Развитие идей и приложений реляционной СУБД System R

         

Распределенная компиляция запросов


Как мы уже отмечали, запросы на языке SQL до своего реального выполнения подвергаются компиляции. Как и в случае System R компиляция запроса может производиться на стадии прекомпиляции прикладной программы, написанной на традиционном языке программирования (PL/1, Cobol, ассемблер) с включением предложений SQL, или в динамике выполнения транзакции при выполнении предложения PREPARE. С точки зрения пользователей процесс компиляции в System R* приводит к тем же результатам, что и в System R: для каждого предложения SQL образуется программа к машинных кодах (секция модуля доступа), вызовы которой помещаются в текст исходной прикладной программы.

Однако, в действительности процесс компиляции запроса в System R* намного более сложен, чем в System R, что и естественно по причине гораздо более сложных сетевых взаимодействий, которые потребуются при реальном выполнении транзакции. Распределенная компиляция запросов в System R* включает множество технических ухищрений и тонкостей. Мы не будем касаться их всех в этой статье по причинам недостатка информации и ограниченности объема. Рассмотрим только общую схему распределенной компиляции.

Следуя [41], будем называть главным узлом тот узел сети, в котором инициирован процесс компиляции предложения SQL, и дополнительными узлами - те узлы, которые вовлекаются в этот процесс в ходе его выполнения. На самом грубом уровне процесс компиляции можно разбить на следующие фазы:

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

2. В главном узле генерируется глобальный план выполнения запроса, в котором учитывается лишь порядок взаимодействий узлов при реальном выполнении запроса. Для выработки глобального плана используется расширение техники оптимизации, применяемой в System R.
На этом вопросе мы остановимся более подробно в следующем подразделе. Глобальный план отображается в преобразованном соответствующим образом дереве запроса. 3. Если в глобальном плане выполнения запроса участвуют дополнительные узлы, производится его декомпозиция на части, каждую из которых можно выполнить в одном узле (например, локальная фильтрация отношения в соответствии с заданным в условии выборки предикате ограничения). Соответствующие части запроса (во внутреннем представлении) рассылаются в дополнительные узлы. 4. В каждом узле, участвующем в глобальном плане выполнения запроса (главном и дополнительных) выполняется завершающая стадия выполнения компиляции. Эта стадия включает, по существу, две последние фазы процесса компиляции запроса в System R: оптимизацию и генерацию машинных кодов. Производится проверка прав пользователя, от имени которого производится компиляция, на выполнение соответствующих действий; происходит обработка представлений базы данных (здесь имеются тонкости, связанные с тем, что представления могут включать удаленные отношения; ниже мы еще остановимся на этом, а пока будем считать, что в запросе употребляются только имена базовых отношений); осуществляется локальная оптимизация обрабатываемой части запроса в соответствии с имеющимися индексами; наконец, производится генерация кода. В отличие от секций модуля доступа System R, которые включали только индивидуальный код и обращения к RSS, образовывающиеся при компиляции запроса в System R* программные единицы (подсекции) включают еще и обращения к сетевому компоненту системы для необходимых транспортных взаимодействий. Каждая подсекция помещается в локальный каталог базы данных соответствующего узла, в который, кроме того, заносится информация, характеризующая зависимость корректности программного кода от состояния локальных объектов (например, индексов). Это необходимо в соответствии с требованием локальной автономии узлов. Должно быть возможно произвести некоторые локальные действия (например, уничтожить индекс) без оповещения об этом удаленных узлов.


При выбранной в System R* схеме такое действие приведет к объвлению некорректными всех локальных подсекций модулей доступа, в которых использовался данный индекс. При попытке использования подсекции ее некорректность будет обнаружена, и последует перекомпиляция запроса без какого-либо взаимодействия с другими узлами. Как и в System R, компиляция запросов в System R* производится в пределах некоторой служебной транзакции. Как и вообще в распределенных системах баз данных, управление транзакциями в System R* существенно сложнее, чем в System R. Более подробно мы рассмотрим этот вопрос ниже, а пока заметим, что наиболее важная проблема связана с завершением распределенных транзакций, поскольку изменения, произведенные в распределенной базе данных операциями данной транзакции, должны быть либо зафиксированы во всех участвующих в выполнении транзакции узлах, либо должны полностью отсутствовать. Для достижения этой цели в System R*, как и в большинстве распределенных систем управления базами данных, употребляется двухфазный протокол завершения транзакции. В соответствии с этим протоколом при завершении транзакции все ее участники сначала оповещаются инициатором транзакции о намерении ее завершить, и только затем, в случае, если все участники выразили на это согласие (зафиксировали свои изменения), происходит реальное завершение транзакции со снятием синхронизационных захватов. Так обстоит дело и при завершении транзакции, в рамках которой производилась компиляция запросов (это может быть служебная транзакция, инициированная прекомпилятором, или обычная пользовательская транзакция, в которой выполняется предложение SQL PREPARE) по отношению к произведенным в различных узлах сети подсекциям модуля доступа. Рассмотрим теперь особенности процесса компиляции в System R* запросов, в которых участвуют представления. Как мы уже отмечали, особенностью представлений, допустимых в System R*, является то, что они могут быть определены на отношениях, распределенных в сети. Исходя из того, что одним из предназначений представлений является защита некоторых атрибутов отношений от несанкционированного использования, в компиляторе System R* нельзя было использовать технику слияния дерева запроса с деревьями представлений, поскольку при этом терялась привязка представления к тому узлу, на котором оно было создано.


Из-за этого в некоторых узлах сети могли появиться данные, которые не должны быть видимы в этих узлах по условиям авторизации, т.е. защита могла бы быть нарушена. Поэтому обнаружение того, что отношение является не базовым, а представлением, в System R* производится только в дополнительном узле - владельце представления. В нем и производится слияние поддерева запроса, переданного в дополнительный узел для окончательной обработки, с деревьями представлений. Но в результате этого слияния может образоваться дерево, не все объекты которого являются локальными для этого узла. Если действительно возникает такая ситуация, то дополнительный узел начинает действовать как главный по отношению к выработанному дереву запросу, т.е. в нем вырабатывается глобальный план выполнения части запроса, производится его декомпозиция, и части подзапроса рассылаются в дополнительные узлы. Из публикаций не очень ясно, что будет, если представление определяется не на базовых отношениях, а на представлениях: происходит ли их раскрытие при обработке предложения DEFINE VIEW или откладывается до реального выполнения запроса на представлении верхнего уровня. Мы склоняемся к тому, что разумнее было бы использовать первый подход, но неясно, согласуется ли это с требованиями защиты. Во любом случае способ обработки запросов на представлениях, применяемый в System R*, обеспечивает меньшие возможности оптимизации выполнения таких запросов по сравнению с подхо- дом System R, поскольку при выработке плана выполнения запроса на стадии его компиляции в главном узле в общем случае учитываются не все возможные соединения, которые потребуются при выполнении запроса (некоторые из них могут быть скрыты в представлении). Поэтому в конечном распределенном плане порядок выполнения соединения может оказаться неоптимальным. В публикациях по System R* не отражен вопрос, касающийся поддержки глобальной целостности баз данных. Из общих соображений должно быть разрешено определять условия целостности и условные воздействия, касающиеся удаленных отношений, но в каких узлах нужно проверять условия целостности и выполнять условные воздействия исходя из тех же соображений защиты данных - неясно.Похоже, что этот вопрос не решен в имеющихся реализациях System R*. Здесь особенно трудно выдержать разумный компромисс между базовым требованием максимальной автономности локальных баз данных и желанием обеспечить глобальную автоматическую поддержку целостности распределенной базы данных. | |


Содержание раздела