Порядок соединений
Способов соединить N таблиц - больше факториала от N. На 4-5 таблицах перебор реален, на 10 - миллионы вариантов. Планировщик ищет порядок динамическим программированием, ограничивая себя двумя порогами:
SHOW join_collapse_limit; -- 8: сколько JOIN волен переставлять
SHOW geqo_threshold; -- 12: с какого числа таблиц включить GEQO
Сверх join_collapse_limit порядок берётся как написан;
join_collapse_limit = 1 фиксирует порядок вручную. При числе таблиц
от geqo_threshold включается GEQO - генетический поиск: быстрый, но
недетерминированный и без гарантии оптимума.
Кеш плана
Подготовленное выражение разбирается один раз. Сначала строится custom plan под значения параметров; после ~5 вызовов планировщик может перейти на generic plan (без привязки к значению), если тот не дороже в среднем.
PREPARE q(int) AS SELECT * FROM tickets WHERE flight_id = $1;
SELECT name, generic_plans, custom_plans FROM pg_prepared_statements;
Подводный камень generic plan
На перекошенных данных (значения с разной селективностью) generic plan усредняет и становится плохим для части вызовов. Симптом - «вдруг замедлилось» при том же тексте. Лечение:
SET plan_cache_mode = force_custom_plan;
Время планирования видно в EXPLAIN ANALYZE (Planning Time) и
EXPLAIN (MEMORY). Выбор алгоритма соединения - в join-algorithms.