- •Глава 13. Семантическое моделирование
- •Часть III Проектирование базы данных
- •Часть IV
- •14.1. Введение
- •14.2. Транзакции
- •14.3. Восстановление транзакции
- •14.4. Восстановление системы
- •14.5. Восстановление носителей
- •14.6. Двухфазная фиксация
- •14.7. Поддержка языка sql
- •14.8. Резюме
- •15.1. Введение
- •15.2. Три проблемы параллельности
- •15.3. Блокировка
- •15.4. Устранение трех проблем параллельности
- •15.5. Взаимная блокировка
- •15.6. Упорядочиваемость
- •15.7. Уровни изоляции
- •15.8. Блокировка намерения
- •15.9. Средства языка sql
- •15.10. Резюме
- •Часть V
- •16.1. Введение
- •16.2. Избирательная схема управления доступом
- •16.3. Мандатная схема управления доступом
- •16.4. Статистические базы данных
- •16.5. Шифрование данных
- •16.6. Средства языка sql
- •16.7. Резюме
- •17.1. Введение
- •17.2. Пример выполнения оптимизации
- •17.3. Оптимизация запросов
- •17.4. Преобразование выражений
- •17.5. Статистические показатели базы данных
- •17.6. Стратегия по принципу "разделяй и властвуй"
- •17.7. Реализация реляционных операторов
- •17.8. Резюме
- •18.1. Введение
- •18.2. Обзор концепции трехзначной логики
- •18.3. Некоторые следствия изложенной схемы
- •18.4. Отсутствующие значения и ключи
- •18.5. Внешнее соединение
- •18.6. Специальные значения
- •18.7. Поддержка неопределенных значений в языке sql
- •18.8. Резюме
- •Глава 19
- •19.1. Введение
- •19.2. Иерархия типов
- •19.3. Полиморфизм и заменимость
- •19.4. Переменные и операция присвоения
- •19.5. Специализация по ограничениям
- •19.6. Операции сравнения
- •19.7. Операторы, версии и сигнатуры
- •19.8. Является ли окружность эллипсом
- •19.9. Пересмотр специализации ограничением
- •19.10. Резюме
- •20.1. Введение
- •20.2. Предварительные сведения
- •20.3. Двенадцать основных целей
- •1. Локальная независимость
- •2. Отсутствие опоры на центральный узел
- •3. Непрерывное функционирование
- •4. Независимость от расположения
- •5. Независимость от фрагментации
- •6. Независимость от репликации
- •7. Обработка распределенных запросов
- •8. Управление распределенными транзакциями
- •9. Аппаратная независимость
- •10. Независимость от операционной системы
- •11. Независимость от сети
- •12. Независимость от типа субд
- •20.4. Проблемы распределенных систем
- •Транзакция т1х
- •20.5. Системы "клиент/сервер"
- •20.6. Независимость от субд
17.3. Оптимизация запросов
Рассмотрим четыре стадии процесса оптимизации запросов, который схематически представлен на рис. 17.1.
Преобразование запроса во внутреннюю форму.
Преобразование запроса в каноническую форму.
Выбор потенциальных низкоуровневых процедур.
Генерация различных вариантов планов вычисления запроса и выбор плана с ми- нимальными затратами.
Перейдем к подробному рассмотрению каждой стадии процесса оптимизации.
Процессор
языка Сканирование,
манипулирования
обработка представлений,
данными трансляция
Выражение
реляционной
алгебры
Преобразование
выражения,
оценка стоимости
выполнения
и т.д.
Оптимизированный
код
Выполнение
На этой стадии выполняется преобразование запроса в некоторое внутреннее пред- ставление, более удобное для машинных манипуляций. В результате из рассмотрения полностью исключаются конструкции сугубо внешнего уровня (например, разнообраз- ные варианты конкретного синтаксиса используемого языка запросов) и готовится почва для последующих стадий оптимизации.
Замечание. Обработка представлений (т.е. процесс замены ссылок на представления выражениями, определяющими соответствующие представления) также выполняется на этом этапе.
Возникает очевидный вопрос: "Какое формальное представление должно использо- ваться для внутреннего представления запроса?". Независимо от того, какой именно ва- риант формального представления будет выбран, он должен быть достаточно полным, чтобы допускать представление любых запросов, которые могут быть определены на внешнем языке системы. Кроме того, выбранный способ формального представления должен быть нейтральным, насколько это возможно, в том смысле, что он не должен за- ранее предопределять последующих оптимизационных решений. Чаще всего для внут- реннего представления запросов используется та или иная модификация абстрактного синтаксического дерева, которое в этом случае называется деревом запроса. Напри- мер, на рис. 17.2 показано дерево для запроса, рассматривавшегося выше в этой же главе ("Определить имена поставщиков детали с номером 'Р2'").
Окончательный результат
т
Проекция по атрибуту SNAME Т
Выборка кортежей, в которых Pi =
т
т
S
Соединение по атрибуту St Т 1
SP S
'Р2'
Рис. 17.2. Дерево реализации запроса "Определить имена поставщиков детали с но- мером 'Р2'"
Однако для наших целей удобнее всего будет предположить, что для внутреннего представления запросов используется один из тех формальных методов, с которыми мы уже знакомы: реляционная алгебра или реляционное исчисление. В этом случае дерево запроса, подобное представленному на рис. 17.2, можно будет рассматривать просто как альтернативный схематический вариант представления некоторого выражения, записан- ного в нотации одного из двух предложенных выше формальных методов (реляционная алгебра или реляционное исчисление). Предположим, что выбранный формальный метод — реляционная алгебра. С этого момента будем считать, что внутренним пред- ставлением дерева запроса, показанного на рис. 17.2, является следующее алгебраиче- ское выражение.
( ( SP JOIN S } WHERE Pi = Pi ( 'P2' ) ) { SNAME }
Стадия 2. Преобразование запроса в каноническую форму
'
Следует заметить, что язык SQL
исключительно
предрасположен к этому (см. упр. 7.12
в
главе 7, а также [4.18]).
Другие языки (напршиер, языки реляционной
алгебры или исчисления)
обычно не
позволяют создать такое же количество
эквивалентных по результату выражений.
Эта
излишняя "гибкость " языка SQL
на
самом деле усложняет жизнь разработчикам
(а
не поль-
зователям), поскольку
существенно усложняет алгоритм
оптимизатора.
Замечание о канонической форме. Понятие канонической формы является централь- ным во многих разделах математики и связанных с ней дисциплинах. Каноническая форма может быть определена следующим образом. Пусть Q— множество объектов (запросов), и пусть существует понятие об их эквивалентности (а именно: запросы ql и q2 эквивалентны тогда и только тогда, когда дают идентичные результаты). Тогда под- множество С множества Q является подмножеством канонических форм для запросов из множества Q в смысле определенной выше эквивалентности тогда и только тогда, ко- гда каждому объекту q из множества Q соответствует только один объект с из множества С. В этом случае говорят, что объект с является канонической формой объекта q. Все "интересующие" свойства, которыми обладает объект q, также присущи объекту с. По- этому, чтобы доказать различные "интересующие" результаты, достаточно изучить ме- нее мощное множество объектов С, а не более мощное множество Q.
Вернемся к основной теме обсуждения. Чтобы преобразовать результаты выполнения стадии 1 в некоторую эквивалентную, но более эффективную форму, оптимизатор ис- пользует определенные и хорошо известные правила преобразования, или законы. Ниже приведен пример такого правила. Здесь выражение
( A JOIN В ) WHERE <выборка из> А
может быть преобразовано в эквивалентное, но более эффективное выражение ( A WHERE <выборка из> А ) JOIN В
Подобное преобразование кратко рассматривалось в разделе 6.6. Кроме того, оно бы- ло приведено несколько выше, при обсуждении примера в разделе 17.2, который ясно продемонстрировал, зачем нужны подобные преобразования. Многие другие правила преобразования описываются ниже, в разделе 17.4.
Стадия 3. Выбор потенциальных низкоуровневых процедур
После преобразования внутренней формы запроса в более подходящую (каноническую) форму оптимизатор должен решить, как следует выполнять запрос, представленный в этой канонической форме. На данной стадии принимаются во внима- ние наличие индексов и других путей доступа, статистическое распределение сущест- вующих значений данных, физическая кластеризация хранимых данных и т.п. Обратите внимание, что на стадиях 1 и 2 этим аспектам совсем не уделялось внимания.
Основная стратегия состоит в том, чтобы рассматривать выражение запроса как се- рию низкоуровневых операций (соединения, выборки и т.п.), которые в определенной степени зависят одна от другой. Ниже приведен пример такой зависимости. При про- граммной реализации выполнения проекции обычно требуется, чтобы считываемые кор- тежи следовали в определенном порядке; это позволит исключить дублирующиеся ре- зультирующие кортежи. В свою очередь, это означает, что выполняемая непосредствен- но перед проекцией операция должна выдавать выходные кортежи именно в такой, тре- буемой последовательности.
Для каждой низкоуровневой операции (а также, возможно, для нескольких часто встречающихся комбинаций подобных операций) оптимизатор имеет набор низкоуров- невых процедур реализации. Например, существует набор процедур для реализации операции выборки: по условию равенства определенному значению потенциального
ключа; на основе индексированного атрибута, по которому выполняется выборка; на ос- нове хешированного атрибута и т.д. Примеры таких процедур приведены ниже, в разде- ле 17.7 (см. также [17.8]—[ 17.14]).
С каждой процедурой связана и параметризованная формула стоимости, позволяю- щая оценить стоимость выполнения процедуры (т.е. уровень затрат, требуемых для ее выполнения). Чаще всего стоимость определяется на основе подсчета количества необ- ходимых дисковых операций ввода-вывода, но некоторые системы учитывают также время использования процессора и другие факторы. Эти формулы стоимости применя- ются на стадии 4. В [17.8]—[ 17.14] обсуждаются и анализируются формулы стоимости для различных процедур реализации при разных исходных предположениях.
Далее, используя сохраняемую в каталоге информацию о состоянии базы данных (существующие индексы, текущую кардинальность переменных-отношений и т.п.) и све- дения о взаимозависимостях, упоминавшихся выше, оптимизатор выбирает одну или не- сколько процедур-кандидатов для каждой низкоуровневой операции в запросе. Этот процесс обычно называют выбором пути доступа (см. также [17.34], [17.35]).
Замечание. Следует отметить, что в [17.34], [17.35] приведенный термин использует- ся для ссылки на определенные в данной главе стадии 3 и 4, а не только на стадию 3. Действительно, на практике очень трудно разграничить, где заканчивается одна стадия и начинается другая: просто стадия 3 плавно переходит в стадию 4.
Стадия 4. Генерация различных вариантов планов вычисления запроса и выбор плана с минимальными затратами
На последней стадии процесса оптимизации создается набор потенциальных планов запроса, после чего следует выбор лучшего (т.е. наименее дорогого) плана выполнения за- проса. Каждый план выполнения строится как комбинация некоторого набора процедур реализации, причем каждой низкоуровневой операции в запросе соответствует одна проце- дура. Заметьте, что обычно для поступившего запроса вырабатывается множество планов выполнения запроса (возможно, даже слишком много). На практике, вероятно, не стоит ге- нерировать все возможные планы запроса, так как одни из них могут быть комбинаторны- ми версиями других планов выполнения этого же запроса и сам процесс выбора наиболее дешевого плана может стать чрезмерно дорогостоящим. При выборе плана с наименьшей стоимостью рекомендуется (возможно, даже необходимо) руководствоваться некоторыми эвристическими правилами, позволяющими ограничить количество анализируемых планов запросов разумными пределами [17.55]. Практику ограничения количества запросов ра- зумными пределами иначе называют сокращением пространства поиска, поскольку ее можно рассматривать и как уменьшение диапазона ("пространства") анализируемых опти- мизатором вариантов ("поиск") до контролируемых пределов.
Несомненно, для выбора плана с наименьшей стоимостью необходим метод опреде- ления стоимости любого возможного плана. По сути, стоимость плана— это просто сумма стоимостей отдельных процедур, входящих в его состав. Поэтому задача оптими- затора сводится к вычислению формул стоимости для каждой отдельной процедуры. Ос- новная проблема состоит в том, что стоимость выполнения процедуры зависит от разме- ра отношения (или отношений), которое эта процедура обрабатывает. Так как все запро- сы, за исключением самых простых, требуют создания некоторых промежуточных ре-
зультатов выполнения, оптимизатор должен суметь оценить размер этих результатов и использовать полученные значения при вычислении формул стоимости. К сожалению, размеры промежуточных наборов данных сильно зависит от конкретных значений хра- нимых данных, поэтому точная оценка стоимости может оказаться достаточно сложной проблемой. В [17.3], [17.4] обсуждаются некоторые подходы к решению этой проблемы и приводятся ссылки на другие направления исследований.