У меня очень простой запрос, который выполнялся на удивление медленно, и по причинам выяснилось, что он выполнял сканирование представления после выполнения JOIN.Я был немного удивлен, увидев, что, поскольку я ожидал, что Postgres выполнит фильтрацию до присоединения , я увидел, что одна из базовых таблиц имеет INDEX для столбца, который должен быть отфильтрован.
Есть ли способ, которым я могу как-то переупорядочить запрос или подсказать планировщику, как выполнить запрос по-другому?
Имейте в виду, я делаю знаю, как взломать проблему напрямуюдоступ к базовым таблицам, но представление скрывает некоторую сложность, было бы неплохо не указывать в запросах.
Запрос
select * from form where encounter_id= 23728 and type = 'vitals';
EXPLAIN ANALYZE
Subquery Scan on form (cost=0.57..3439.07 rows=1 width=622) (actual time=8.187..8.187 rows=0 loops=1)
Filter: ((form.encounter_id = 23728) AND (form.type = 'vitals'::text))
Rows Removed by Filter: 12000
-> Unique (cost=0.57..3259.07 rows=12000 width=626) (actual time=0.008..7.612 rows=12000 loops=1)
-> Merge Join (cost=0.57..3229.07 rows=12000 width=626) (actual time=0.007..5.485 rows=12000 loops=1)
Merge Cond: (fd.form_id = f.id)
-> Index Scan using _idx_form_details on _form_details fd (cost=0.29..2636.78 rows=12000 width=603) (actual time=0.003..1.918 rows=12000 loops=1)
-> Index Scan using pk_form on _form f (cost=0.29..412.29 rows=12000 width=27) (actual time=0.002..1.214 rows=12000 loops=1)
Planning time: 0.170 ms
Execution time: 8.212 ms
Определения TABLE и VIEW
CREATE TABLE _form (
id INT NOT NULL,
encounter_id INT REFERENCES _encounter (id) NOT NULL,
type TEXT NOT NULL,
CONSTRAINT pk_form PRIMARY KEY (id),
FOREIGN KEY (cid) REFERENCES _user_in_role (id)
);
CREATE INDEX encounter_id ON _form (encounter_id, type);
CREATE TABLE _form_details (
id INT NOT NULL,
form_id INT REFERENCES _form (id) NOT NULL,
archived BOOLEAN NOT NULL DEFAULT FALSE,
CONSTRAINT pk_form_details PRIMARY KEY (id),
FOREIGN KEY (cid) REFERENCES _user_in_role (id)
);
CREATE VIEW form AS
SELECT DISTINCT ON (f.id)
f.id,
f.encounter_id,
f.type,
fd.archived,
f.cid
FROM _form f
JOIN _form_details fd
ON (f.id = fd.form_id)
ORDER BY f.id, fd.id DESC;
РЕДАКТИРОВАТЬ: Кто-то отправил ответ (впоследствии удален), которая содержала важный фрагмент информации: даже если столбец encounter_id
в базовой таблице проиндексирован, операция ORDER BY
в VIEW не отвечает своей цели.К сожалению, мы не можем избавиться от ORDER BY
, поскольку это необходимо для работы DISTINCT ON
.