Установим параметры, которые покажут примерное время выполнения этапов обработки:
=> ALTER SYSTEM SET log_parser_stats = on;
ALTER SYSTEM
=> ALTER SYSTEM SET log_planner_stats = on;
ALTER SYSTEM
=> ALTER SYSTEM SET log_executor_stats = on;
ALTER SYSTEM
=> SELECT pg_reload_conf();
pg_reload_conf ---------------- t (1 row)
Обычный удобный способ узнать время выполнения и время планирования (включая разбор и переписывание) - команда EXPLAIN ANALYZE. Ее основное назначение - показать план выполнения запроса, но о плане как таковом мы будем говорить позже. Пока обратите внимание на две последние строки:
=> EXPLAIN (ANALYZE, COSTS OFF, TIMING OFF) SELECT * FROM ticket_flights;
QUERY PLAN ---------------------------------------------------------- Seq Scan on ticket_flights (actual rows=8391852 loops=1) Planning time: 4.235 ms Execution time: 1993.501 ms (3 rows)
Благодаря установленным нами параметрам, из журнала сообщений можно получить более подробную информацию, хотя обычно это и не требуется. Выведем только основные цифры (elapsed):
postgres$ tail -n 50 /var/log/postgresql/postgresql-10-main.log | egrep 'LOG: |elapsed'
2019-02-13 13:02:46.387 MSK [3054] postgres@demo LOG: PARSER STATISTICS ! 0.000000 s user, 0.000000 s system, 0.000029 s elapsed 2019-02-13 13:02:46.392 MSK [3054] postgres@demo LOG: PARSE ANALYSIS STATISTICS ! 0.000000 s user, 0.000000 s system, 0.005306 s elapsed 2019-02-13 13:02:46.392 MSK [3054] postgres@demo LOG: REWRITER STATISTICS ! 0.000000 s user, 0.000000 s system, 0.000001 s elapsed 2019-02-13 13:02:46.397 MSK [3054] postgres@demo LOG: PLANNER STATISTICS ! 0.000000 s user, 0.004000 s system, 0.004176 s elapsed 2019-02-13 13:02:48.391 MSK [3054] postgres@demo LOG: EXECUTOR STATISTICS ! 0.536000 s user, 0.616000 s system, 1.997833 s elapsed
Разные способы измерения выдают несколько отличающиеся результаты.
Протокол простых запросов применяется, когда на сервер просто отправляется оператор (и, если это SELECT или команда с фразой RETURNING, то мы ожидаем получение всех строк результата). Например:
=> SELECT model FROM aircrafts WHERE aircraft_code = '773';
model --------------- Боинг 777-300 (1 row)
Создадим подготовленный оператор для нашего запроса:
=> PREPARE model(varchar) AS SELECT model FROM aircrafts WHERE aircraft_code = $1;
PREPARE
Теперь мы можем вызывать оператор по имени:
=> EXECUTE model('773');
model --------------- Боинг 777-300 (1 row)
=> EXECUTE model('763');
model --------------- Боинг 767-300 (1 row)
Все подготовленные операторы можно увидеть в представлении:
=> SELECT * FROM pg_prepared_statements \gx
-[ RECORD 1 ]---+-------------------------------------------------------- name | model statement | PREPARE model(varchar) AS + | SELECT model FROM aircrafts WHERE aircraft_code = $1; prepare_time | 2019-02-13 13:02:48.603462+03 parameter_types | {"character varying"} from_sql | t
Если подготовленный оператор больше не нужен, его можно удалить командой DEALLOCATE, но в любом случае оператор пропадет при завершении сеанса.
=> \c
You are now connected to database "demo" as user "postgres".
=> SELECT * FROM pg_prepared_statements;
name | statement | prepare_time | parameter_types | from_sql ------+-----------+--------------+-----------------+---------- (0 rows)
Команды PREPARE, EXECUTE, DEALLOCATE - команды SQL. Клиенты на других языках программирования будут использовать операции, определенные в соответствующем драйвере. Но любой драйвер использует один и тот же протокол для взаимодействия с сервером.
Курсоры дают возможность построчной обработки результата. Они часто используются в приложениях и имеют особенности, связанные с оптимизацией.
На SQL использование курсоров можно продемонстрировать следующим образом. Объявляем (и сразу же открываем) курсор и выбираем первую строку:
=> BEGIN;
BEGIN
=> DECLARE c CURSOR FOR SELECT * FROM aircrafts;
DECLARE CURSOR
=> FETCH c;
aircraft_code | model | range ---------------+---------------+------- 773 | Боинг 777-300 | 11100 (1 row)
Читаем вторую строку результата и закрываем открытый курсор.
=> FETCH c;
aircraft_code | model | range ---------------+---------------+------- 763 | Боинг 767-300 | 7900 (1 row)
=> CLOSE c;
CLOSE CURSOR
=> COMMIT;
COMMIT
Конец демонстрации.