Ваш текущий план выполнения показывает, что Postgres вообще не использует указанный вами индекс. Скорее, он просто выполняет два последовательных сканирования каждой таблицы, что не будет особенно эффективно, если эти таблицы большие.
Во-первых, AFAIK ваш запрос будет выполнен так же, как это:
SELECT COUNT(id)
FROM table_a
WHERE
approval_status = 2 AND
is_locked = true AND
EXISTS (SELECT 1 from table_b WHERE table_b.tba_id = table_a.id AND table_b.status = 2)
GROUP BY company_id;
То есть фильтр Postgres действительно будет вести себя так же, как если бы эта логика была в формальном предложении WHERE
.
Я бы предложил создать индекс для каждой из двух таблиц:
CREATE INDEX table_a_idx ON table_a (approval_status, is_locked, company_id);
CREATE INDEX table_b_idx ON table_b (status, tba_id);
Основанием для индекса table_a_idx
является то, что мы хотим удалить как можно больше записей, используя фильтры approval_status
и is_locked
. Я также включил company_id
в этот индекс, чтобы охватить столбец GROUP BY
, надеясь избежать необходимости дополнительного чтения с диска после обхода индекса.
table_b_idx
существует для ускорения предложения EXISTS
вашего запроса.
Я бы также рекомендовал использовать COUNT(*)
вместо COUNT(id)
.