Есть по крайней мере пара похожих (но не совсем одинаковых ) вопросов по SO. В этих вопросах проблема производительности запросов заключается в отсутствии индексов или избыточных предикатов.
Но мой случай прост и понятен: 3 таблицы, каждая ссылается на другую. Есть индексы BTree для каждой строки таблицы ссылок . Вот таблицы:
CREATE TABLE region(
id serial PRIMARY KEY,
title VARCHAR (50) NOT NULL
);
CREATE TABLE unit(
id serial PRIMARY KEY,
region_id INT NOT NULL REFERENCES region(id)
);
CREATE TABLE unit_usage(
id serial PRIMARY KEY,
title VARCHAR (50) NOT NULL,
unit_id INT NOT NULL REFERENCES unit(id)
);
CREATE INDEX ON unit ((region_id));
CREATE INDEX ON unit_usage ((unit_id));
CREATE INDEX ON unit_usage ((title));
В таблице unit_usage содержится более 300 000 000 строк, более 50 000 000 строк в таблице юнитов и более 65 000 строк в таблице регионов. Я хочу запросить количество регионов для каждого unit_usage . Примерно так:
WITH x AS
(
select u.region_id as region_id, t.title as title
from unit_usage t join unit u
on t.unit_id = u.id
)
SELECT title, count(region_id) as found_in_regions
FROM x GROUP BY title;
Здесь ' DBFiddle .
Этот запрос выполняется около 5 минут. Это слишком много - мой лимит составляет около 10 секунд. Что я пробовал:
переформировать запрос, например:
select u.region_id, t.title, count(t.id)
from unit_usage t join unit u
on t.unit_id = u.id group by u.region_id, t.title;
то же время выполнения.
- setting enable_hashjoin = off; Я избавился от Ha sh Join и одного из Seq Scan, но это не влияет на время выполнения