Как работает исполнитель PostgreSQL
Исполнитель принимает план, созданный планировщиком/исполнителем, и обрабатывает его рекурсивно, чтобы получить требуемый набор строк. Обработка выполняется по конвейеру, с получением данных по требованию. При вызове любого узла плана он должен выдать очередную строку, либо сообщить, что выдача строк завершена.
В каждом узле плана есть функции, предназначенные для выполнения соответствующей операции. Эти функции находятся в каталоге src/backend/executor/.
Например, функции для выполнения последовательного сканирования (ScanScan) определены в nodeSeqscan.c; функции для выполнения индексного сканирования (IndexScanNode) определены в nodeIndexscan.c; функции для сортировки SortNode определены в nodeSort.c и так далее.
Безусловно, лучший способ понять, как работает исполнитель, - это прочитать вывод команды EXPLAIN. Обратите внимание на пример 1 в разделе 3.3.
testdb=# EXPLAIN SELECT * FROM tbl_1 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_1 (cost=0.00..170.00 rows=300 width=8)
Filter: (id < 300)
(4 rows)
Как работает исполнитель. Прочитаем результат команды EXPLAIN, двигаясь от нижней строки к верхней.
- Строка 6: Сначала исполнитель выполняет операцию последовательного сканирования, используя функции, определенные в nodeSeqscan.c.
- Строка 4: Далее исполнитель сортирует результат последовательного сканирования с помощью функций, определенных в nodeSort.c.
Примечание: Временные файлы
Помимо буферов work_men и temp_buffers, используемых для обработки запроса, исполнитель также использует и временные файлы.
Используя опцию ANALYZE, команда EXPLAIN фактически выполняет запрос и отображает истинное количество строк, время выполнения запроса и фактическое использование памяти.
Пример показан ниже:
testdb=# EXPLAIN ANALYZE SELECT id, data FROM tbl_25m ORDER BY id;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
Sort (cost=3944070.01..3945895.01 rows=730000 width=4104) (actual time=885.648..1033.746 rows=730000 loops=1)
Sort Key: id
Sort Method: external sort Disk: 10000kB
-> Seq Scan on tbl_25m (cost=0.00..10531.00 rows=730000 width=4104) (actual time=0.024..102.548 rows=730000 loops=1)
Planning time: 1.548 ms
Execution time: 1109.571 ms
(6 rows)
В строке 6 команда EXPLAIN показывает, что исполнитель использовал временный файл, размер которого составляет 10000 килобайт.
Временные файлы создаются внутри PGDATA/base/pgsql_tmp или внутри подкаталога pgsql_tmp каталога табличного пространства, если для них определено табличное пространство, отличное от pg_default. Имя временного файла имеет форму pgsql_tmp PPP.NNN, где PPP — PID серверного процесса, а NNN служит для разделения различных временных файлов этого серверного процесса:
{"pgsql_tmp"}+{PID of the postgres process which creates the file} . {sequencial number from0}
Например, временный файл 'pgsql_tmp8903.5' - временный файл, созданный процессом postgres с pid 8903.
$ ls -la /usr/local/pgsql/data/base/pgsql_tmp* -rw------- 1 postgres postgres 10240000 12 4 14:18 pgsql_tmp890



