=====Обработка запросов===== Обработка запросов - одна из самых сложных подсистем PostgreSQL. PostgreSQL поддерживает множество функций, требуемых стандартами SQL, и обрабатывает запросы наиболее эффективным способом. \\ {{ :postgres:основы:query-processing-1.png?nolink |}} \\ Хотя несколько фоновых рабочих процессов используются для параллельной обработки запросов в PostgreSQL, который поставляется с версией 9.6, в основном все запросы, отправленные подключенным клиентом, обрабатываются внутренним процессом. бэкэнд-процесс; Он состоит из пяти подсистем: Parser, Analyzer, Rewriter, Planner и Executor. |**''Parser''**|Создает дерево синтаксического анализа из простого текстового оператора SQL| |**''Analyzer/Analyser''**|Он выполняет семантический анализ дерева синтаксического анализа и создает дерево запросов.| |**''Rewriter''**|Он преобразует дерево запросов, используя правила в системе правил, если таковые имеются.| |**''Planner''**|Он создает дерево плана, которое может быть наиболее эффективно выполнено из дерева запросов.| |**''Executor''**|Выполняет запрос, обращаясь к таблицам и индексам в порядке, созданном деревом плана.| ====Parser==== Дерево синтаксического анализа: это структура данных, определенная из файла parsenodes.h с корневым узлом SelectStmt. На рис. 2 (b) (a) представлено дерево синтаксического анализа образца запроса. \\ {{ :postgres:основы:query-processing-1.2.png?nolink |}} \\ На этом шаге проверяется только синтаксис ввода, в случае ошибки возвращается сообщение об ошибке. Синтаксический анализатор не обрабатывает входящий запрос семантически, поэтому даже если запрос содержит несуществующую таблицу, синтаксический анализатор не возвращает ошибку. Семантические проверки выполняются Analyzer. ====Analyzer==== Analyzer выполняет семантический анализ дерева синтаксического анализа, созданного парсером, и создает дерево запросов. Корневой узел дерева запросов находится в структуре запроса, определенной в файле parsenodes.h. Дерево запроса содержит метаданные входящего запроса. \\ {{ :postgres:основы:query-processing-1.3.png?nolink |}} \\ * targetList - это список столбцов, запрошенных в запросе. В этом примере список содержит столбцы «id» и «data». Если дерево входящего запроса содержит * (звездочку), анализатор меняет его для всех столбцов. * rtable (таблица диапазонов) хранит список отношений, используемых в запросе. * Jointree сохраняет предложения FROM и WHERE. * sortClause - это список SortGroupClause. ====Rewriter==== Rewriter - это система, которая преобразует дерево запросов в соответствии с правилами, хранящимися в системном каталоге pg_rules. Представления - это пример системы правил. Когда представление определяется с помощью CREATE VIEW, соответствующее правило автоматически создается и сохраняется в каталоге. Предположим, что следующее представление предопределено и соответствующее правило хранится в системном каталоге pg_rules. sampledb=# CREATE VIEW employees_list AS SELECT e.id, e.name, d.name AS department FROM employees AS e, departments AS d WHERE e.department_id = d.id; Учитывая запрос, содержащий представление, синтаксический анализатор создает дерево синтаксического анализа, как показано на рисунке 4 (а). sampledb=# SELECT * FROM employees_list; Rewriter теперь обрабатывает узел таблицы диапазонов для дерева синтаксического анализа подзапроса. это соответствующее представление в pg_rules. \\ {{ :postgres:основы:query-processing-1.4.png?nolink |}} \\ ====Planner ve Executor==== В обязанности планировщика входит сканирование дерева запросов и поиск всех возможных планов выполнения запроса. На этом этапе дерево запросов берется из модуля перезаписи и создается дерево плана, которое исполнитель может обработать наиболее эффективно. Сгенерированный план может включать последовательное сканирование или сканирование индекса, если определен полезный индекс. Если запрос содержит две или более таблиц, планировщик может предложить несколько различных способов объединения таблиц. Как и в случае с другими СУБД, вы можете увидеть, как планировщик решает выполнить запрос с помощью команды EXPLAIN. testdb=# EXPLAIN SELECT * FROM tbl_a WHERE id < 300 ORDER BY data; QUERY PLAN --------------------------------------------------------------- Sort (cost=182.34..183.09 rows=300 width=8) Sort Key: data -> Seq Scan on tbl_a (cost=0.00..170.00 rows=300 width=8) Filter: (id < 300) Дерево плана состоит из элементов, называемых узлами плана, связанных со списком * plantree структуры PlannedStmt. Эти элементы определены в файле plannodes.h. Каждый узел плана содержит информацию, которую исполнитель должен обработать. Executor обрабатывает запросы отдельной таблицы от конца дерева плана до корневого узла. Например, дерево плана на рисунке 5 представляет собой список узлов сортировки и узлов последовательного сканирования. Сначала программа-исполнитель последовательно просматривает таблицу и сортирует результаты. \\ {{ :postgres:основы:query-processing-1.6.png?nolink |}} \\ Executor выполняет операции чтения и записи в таблицах и индексах в кластере через диспетчер буферов. При обработке запросов исполнитель использует предварительно выделенные области памяти temp_buffers и work_mem и при необходимости может создавать временные файлы. Кроме того, при доступе к кортежам PostgreSQL он использует механизм управления параллелизмом для согласованности и изоляции выполняющихся транзакций.