29.2.24

Стандартные шаги исполнения запроса


По материалам статьи Craig Freedman: The Building Blocks of Query Execution

Что такое итератор?

SQL Server декомпозирует запросы, преобразуя их в набор стандартных блоков-примитивов, которые принято называть операторами или итераторами. Каждый итератор служит для выполнения одной операции, например, просмотр (сканирование), изменение, фильтрация или соединение данных таблиц, а также соединение двух наборов данных. Всего известно несколько дюжин таких примитивных итераторов. Итераторы могут иметь одну или несколько дочерних записей и могут объединяться в деревья, которые принято называть планом исполнения запроса. Любая инструкция SQL выполняется по соответствующему плану запроса. Для одной инструкции на практике может существовать много правильных планов исполнения запроса. Оптимизатор запросов старается найти лучший (например, самым дешевый) план запроса для каждой инструкции.

Как итератор работает?

Итератор получает на входе считанные строки, полученные из источника данных (например, из таблицы или ее производных), и создаёт результирующие строки, которые поступают на выход и возвращаются вызвавшему итератор объекту. Строки на выходе, которые были сгенерированы итератором, зависят от операции, которую это итератор исполняет.
Все итераторы выполняют одинаковый набор основных методов. Например, метод Open указывает итератору подготовить генерацию строки на выходе, в то время как метод GetRow запрашивает у итератора непосредственную генерацию новой строки и её вывод. Поскольку все итераторы реализуют одинаковые методы, они независимы друг от друга. То есть итератору не нужно иметь знания об его дочерних или родительских записях. Следовательно, итераторы легко объединяются разными способами и в разные планы исполнения запроса.
Когда SQL Server выполняет план запроса, потоки управления направлены вниз дерева запроса. То есть, для итератора в корне плана запроса происходит вызов методов Open и GetRow, и вызовы этих методов распространяются вниз, через всё дерево, до итераторов листового уровня. Поток данных или, более точно, движение по дереву, обеспечивается тем, что итератор вызывает метод GetRow другого итератора.

Простой пример

Рассмотрим следующий запрос:

select count(*)   from t

Самым простым способом исполнения этого запроса является просмотр всех строку в таблице [t] и подсчёт этих строк. Для достижения этого результата, SQL Server использует два итератора: первый для просмотра строк в [t], и второй для их подсчёта:

 <-- count(*) <-- Scan [t]

Для выполнения этого плана запроса вызывается метод Open итератора count(*). Итератор count(*) в методе Open исполняет следующие задачи:

  1. Вызов всех методов Open итератора просмотра, которые подготавливают просмотр, чтобы выдать строки;

  2. Вызовы методов GetRow при просмотре для считывания возвращаемых строк, и с остановкой только тогда, когда возвращаемый GetRow результат говорит о том, что был достигнут конец просмотра;

  3. Вызов метода Close итератора просмотра для указания завершения работы.

Таким образом, к тому времени, когда итератор count() возвратится из Open, он уже вычислит число строк в [t]. Чтобы закончить работу, для count() вызывается GetRow, который возвращает результат запроса (технически, GetRow для count() вызывается не один раз, поскольку заранее неизвестно, что count() выдаст только одну строку, пока не будет вызван этот метод. Второй вызов GetRow возвращает значение, которое говорит о
том, что был достигнут конец результирующего набора).

Обратите внимание, что итератор count() не имеет информации о том, что он считает строки просмотра; он точно так же будет считать строки любого поддерева, которое будет помещено ниже него, независимо от того, насколько простым или сложным это поддерево может быть.

И, наконец, просмотр выполнялся с использованием привязанного к имени таблицы итератора просмотра, в то время как операция count() фактически осуществлялась
с использованием итератора агрегации потока. Мы углубимся в подробные детали
работы разных итераторов, поддерживаемых в SQL Server, в следующих статьях

Комментариев нет:

Отправить комментарий