Скажем, у нас есть следующая схема БД Postgres:
CREATE TABLE users
(
id serial PRIMARY KEY,
name text,
birthdate date NOT NULL
);
INSERT INTO users (id, name, birthdate) VALUES
(1, 'Joe', '2018-01-01'),
(2, 'Robert', '2017-01-02'),
(3, 'Mike', '1997-03-01');
И мы выполняем запрос, подобный этому:
(SELECT * FROM users) UNION (SELECT * FROM users)
Ссылка на SQLfiddle с этим примером
тогда EXPLAIN
результаты, которые мы получаем следующим образом :
HashAggregate (cost=86.00..110.00 rows=2400 width=40)
Group Key: users.id, users.name, users.birthdate
-> Append (cost=0.00..68.00 rows=2400 width=40)
-> Seq Scan on users (cost=0.00..22.00 rows=1200 width=40)
-> Seq Scan on users users_1 (cost=0.00..22.00 rows=1200 width=40)
Кажется, что Postgres выполняет два последовательных сканирования таблицы users
, добавляярезультаты и отбрасывание дубликатов.
Есть ли причина, по которой Postgres не понимает, что этот запрос может быть упрощен до SELECT * FROM users
?
Данный пример, конечно, супер-просто, и если подобные запросы написаны от руки, мы можем понять, что можем оптимизировать их.Но в реальном проекте, над которым я работаю, у нас есть запросы, сгенерированные из набора объектов «правил»: некоторые из подзапросов в правилах зависят от времени (A: «пользователь присоединился менее чем за X дней»назад '), но многие нет (B: «пользователь-женщина»).
При объединении этих правил для просмотра, например, результатов за последние три дня, мы имеем что-то вроде (A UNION B) UNION (A' UNION B) UNION (A'' UNION B)
, которое можно упроститьна A UNION A' UNION A''' UNION B
, но в настоящее время не похоже, что Postgres делает это.
И связанные с этим, многие из этих подзапросов выполняют одинаковые ВНУТРЕННИЕ СОЕДИНЕНИЯ с другими таблицами, но кажется, что все эти таблицыповторяется также в каждом из подзапросов.
Может ли это быть выполнено путем добавления правильных индексов, добавления некоторых подсказок к запросам или чего-то еще, или это просто оптимизация, которую в настоящее время выполняет Postgresне делать во время планирования запроса?