2016-07-29 4 views
1

Ive очень странная проблема, когда я выполнить запрос, как показано ниже:странного исполнения Postgres запрос

with ap as (
    SELECT id from adress limit 1000) 
) 

SELECT distinct house.id, house.date 
FROM house 
WHERE house.adressid in (select id from ap) 

LIMIT 9999 

Я Г.Е. resulkts в пределах 100 мса

Но когда я изменить лимит до 10, то Im становившегося результат после 20 лет

with ap as (
    SELECT id from adress limit 1000) 
) 

SELECT distinct house.id, house.date 
FROM house 
WHERE house.adressid in (select id from ap) 

LIMIT 10 

конечно, есть индекс adressid

CREATE INDEX house_idx 
    ON house 
    USING btree 
    (adressid COLLATE pg_catalog."default"); 

В доме есть 9 миллионов рядов.

Есть ли у кого-нибудь идеи hoiw, я могу попытаться улучшить производительность. Ive сводит проблему к этому очень простой, но в действительности структура является гораздо более сложным вот почему я не предоставить вам таблицы создать и запрос планы ...

+3

Я хотел бы начать с помощью EXPLAIN ANALYZE, чтобы узнать, как на самом деле PostgreSQL обработки двух запросов. – Gary

+0

Возможно, вы упростили запрос. Postgres (если только он не имеет очень необычной оптимизации) должен выполнять одну и ту же работу для обоих запросов - он должен сгенерировать весь список для 'select different' до применения внешнего' limit'. Возможно, что-то еще происходит. –

+0

На самом деле это единственное, что меняет – Snorlax

ответ

0

Это на самом деле не удивительно:

В первом case ap имеет до 1000 строк, а результирующий набор должен иметь до 9999, поэтому оптимизатор положил adress. С индексом на house производительность запросов относительно высока.

Во втором случае ap до сих пор до 1000 строк, но результирующий набор должен иметь только до 10, поэтому оптимизатор поставил house первого ... и заканчивается 10 сканирование таблиц на adress до 1000 строк каждый. Вероятно, он не сможет даже использовать индекс, поскольку в любом месте нет предложения Order By.

Это limit 1000 на адрес выглядит очень подозрительно и потенциально может привести к противоречивым результатам: без Order By нет никакой гарантии, какие записи из adress будет принято во внимание при каждом запуске.

Я хотел бы использовать INNER JOIN, чтобы решить эту проблему:

SELECT DISTINCT house.id, house.date 
FROM house 
INNER JOIN adress ON adress.id = house.adressid 
ORDER BY house.date --< To add some consistency 
LIMIT 10 
Смежные вопросы