Ваш запрос уже выглядит хорошо. Вместо него используйте [INNER] JOIN
или LEFT [OUTER] JOIN
, как предложил Гордон. Но это не сильно изменится.
Вы упомянули, что в таблице B
есть только ...
максимум из ста строк
в то время как таблица A
имеет ...
тысячи строк
Если , то в created_by
имеется много строк (что и следовало ожидать), то есть вероятность для эмулируемого сканирования с пропуском индекса .
(необходимость его эмуляции может go удалить в одном из следующих Postgres версий .)
Основным ингредиентом является многоколонный индекс :
CREATE INDEX ON a (org_id, created_by);
Может замените простым индексом на (org_id)
и он также работает для вашего простого запроса. См .:
В вашем случае есть два осложнения:
DISTINCT
- 0-n
org_id
в результате org_name like '%myorg%'
Таким образом, реализовать оптимизацию сложнее. Но все еще возможно с некоторой фантазией SQL:
SELECT count(DISTINCT created_by) -- does not count NULL (as desired)
FROM b
CROSS JOIN LATERAL (
WITH RECURSIVE t AS (
( -- parentheses required
SELECT created_by
FROM a
WHERE org_id = b.org_id
ORDER BY created_by
LIMIT 1
)
UNION ALL
SELECT (SELECT created_by
FROM a
WHERE org_id = b.org_id
AND created_by > t.created_by
ORDER BY created_by
LIMIT 1)
FROM t
WHERE t.created_by IS NOT NULL -- stop recursion
)
TABLE t
) a
WHERE b.org_name LIKE '%myorg%';
db <> fiddle здесь (Postgres 12, но работает в Postgres 9.6 как хорошо.)
Это рекурсивный CTE в подзапросе LATERAL
, использующий коррелированный подзапрос.
Он использует многостолбцовый индекс сверху для получения только один ряд для каждого (org_id, created_by)
. При сканировании только по индексу, если таблица достаточно вакуумирована.
Основная цель изощренного SQL - полностью избежать последовательного сканирования (или даже сканирования индекса растрового изображения) при большая таблица и читает только очень мало быстрых индексных кортежей.
Из-за дополнительных издержек это может быть немного медленнее для неблагоприятного распределения данных ( много org_id
и / или только несколько строк на created_by
) Но это намного быстрее для благоприятных условий и отлично масштабируется, даже для миллионов строк. Вам нужно проверить, чтобы найти наилучшее место.
Связанный: