Попробуйте эту переписанную версию:
SELECT fat.*
FROM Table1 fat
JOIN conciliacao_vendas cv USING (empresa_id, chavefato, rede_id)
JOIN loja lj ON lj.id = fat.loja_id
JOIN rede rd ON rd.id = fat.rede_id
JOIN bandeira bd ON bd.id = fat.bandeira_id
JOIN produto pd ON pd.id = fat.produto_id
JOIN loja_extensao le ON le.id = fat.loja_extensao_id
JOIN conta ct ON ct.id = fat.conta_id
JOIN banco bc ON bc.id = ct.banco_id
LEFT JOIN modo_captura mc ON mc.id = fat.modo_captura_id
WHERE cv.controle_upload_arquivo_id = 6906
AND fat.parcela = 1
ORDER BY fat.data_venda, fat.data_credito
LIMIT 20;
Синтаксис JOIN и последовательность соединений
В частности, я исправил вводящий в заблуждение LEFT JOIN
на conciliacao_vendas
, который в любом случае вынужден действовать как обычный [INNER] JOIN
из-за более позднего условия WHERE
. Это должно упростить планирование запросов и позволить исключить строки на ранних этапах процесса, что должно сделать все намного дешевле. Связанный ответ с подробным объяснением:
USING
- это просто синтаксическое сокращение.
Поскольку в запросе задействовано много таблиц, а порядок, в котором переписанный запрос объединяет таблицы, теперь оптимален, вы можете точно настроить это с помощью SET LOCAL join_collapse_limit = 1
, чтобы сократить накладные расходы на планирование и избежать некачественных планов запросов. Запустите в одной транзакции:
BEGIN;
SET LOCAL join_collapse_limit = 1;
SELECT ...; -- read data here
COMMIT; -- or ROOLBACK;
Подробнее об этом:
Показатель
Добавьте несколько индексов в справочные таблицы с лотами или строками (не обязательно всего пару десятков), в частности (взятые из вашего плана запроса):
Seq Scan на public.conta ct ... rows=6771
Seq Scan на public.loja lj ... rows=1568
Seq Scan на public .loja_extensao le ... rows=16394
Это особенно странно, потому что эти столбцы выглядят как столбцы первичного ключа и уже должны иметь индекс...
So:
CREATE INDEX conta_pkey_idx ON public.conta (id);
CREATE INDEX loja_pkey_idx ON public.loja (id);
CREATE INDEX loja_extensao_pkey_idx ON public.loja_extensao (id);
Чтобы сделать это действительно жирным, многоколоночный индекс был бы очень кстати:
CREATE INDEX foo ON Table1 (parcela, data_venda, data_credito);
person
Erwin Brandstetter
schedule
30.07.2014
ON mc.id = fat.modo_captura_id AND fat.parcela = 1
может быть намного быстрее... Это действительно зависит от того, КАК движок генерирует результаты. - person xQbert   schedule 30.07.2014INNER JOIN, CROSS JOIN, or unadorned JOIN
.LEFT JOIN
ограничивает планировщика в его выборе. - person Erwin Brandstetter   schedule 30.07.2014