web-dev-qa-db-ja.com

PostgreSQLのcount(*)が常に遅い場合、複雑なクエリをページ分割する方法は?

PostgreSQLのcount(*)常に遅い の場合、複雑なクエリにページ番号を付ける方法は?

トリガーを作成することは、この場合に多くのページ(たとえば、異なるカテゴリ、フィルターなど)がある限り、良い解決策ではないようです。

_VACUUM/VACUUM ANALYZE/ANALYZE/VACUUM FULL_が役に立たない場合はどうしますか? postgresqlでcount(*)を使用するためのベストプラクティスは何ですか?

24
Daniil Ryzhkov

その記事の見出しを読みましたか?

次の記事は9.2より前のバージョンのPostgreSQLにのみ適用されることに注意してください。インデックスのみのスキャンが実装されました。

9.2を使用すると、通常ははるかに良い結果が得られます。詳細は 索引のみのスキャンwikiページ を参照してください。

とはいえ、LIMITOFFSETを使用する古いバージョンでは、通常は問題なく動作します。多少の変動が気にならない場合は、テーブル統計を使用して行数(したがってページ数)を推定できます。 「行数の見積もり」 すでにリンクしている記事の中で を参照してください。

LIMITOFFSETを使用したページ付けは、IMO、とにかくアンチパターンです。多くの場合、ページネーションコードを言い換えてsort_column > 'last_seen_value' LIMIT 100、つまりオフセットを回避します。これにより、パフォーマンスが大幅に向上する場合があります。

19
Craig Ringer

SELECT count(*)FROM tableを実行していて、pg statsを有効にしている場合は、下の例を使用できます。この例では、13msから0.05msになります。

SELECT count(*) FROM news;

26171

EXPLAIN ANALYZE SELECT count(*) FROM news;

合計実行時間:13.057ミリ秒

SELECT reltuples::bigint AS count FROM pg_class WHERE oid = 'public.news'::regclass;

26171

EXPLAIN ANALYZE SELECT reltuples::bigint AS count FROM pg_class WHERE oid = 'public.news'::regclass;

合計実行時間:0.053ミリ秒

13
Mark Selby