Второто изявление отнема много време, защото трябва да сканира цялата таблица, за да преброи редовете.
Едно нещо, което можете да направите, е да използвате индекс:
CREATE INDEX ON tbl_oplog (deleted) INCLUDE (id);
VACUUM tbl_oplog; -- so you get an index only scan
Ако приемем, че id
е първичният ключ, би било много по-добре да използвате count(*)
и пропуснете INCLUDE
клауза от индекса.
Но най-добре вероятно е да използвате оценка:
SELECT t.reltuples * freq.f AS estimated_rows
FROM pg_stats AS s
JOIN pg_namespace AS n
ON s.schemaname = n.nspname
JOIN pg_class AS t
ON s.tablename = t.relname
AND n.oid = t.relnamespace
CROSS JOIN LATERAL
unnest(s.most_common_vals::text::boolean[]) WITH ORDINALITY AS val(v,id)
JOIN LATERAL
unnest(s.most_common_freqs) WITH ORDINALITY AS freq(f,id)
USING (id)
WHERE s.tablename = 'tbl_oplog'
AND s.attname = 'deleted'
AND val.v = ?;
Това използва статистическите данни за разпространението, за да оцени желания брой.
Ако става въпрос само за пагинация, нямате нужда от точен брой.
Прочетете моя блог за повече по темата за броенето в PostgreSQL.