Sql

PostgreSQLでテーブルの行数をすばやく検出する方法



Fast Way Discover Row Count Table Postgresql



解決:

の行を数える 大きい PostgreSQLではテーブルが遅いことが知られています。正確な数を取得するには、MVCCの性質上、行を完全にカウントする必要があります。する方法があります これを劇的にスピードアップ カウントする場合 いいえ する必要があります ちょうど あなたの場合のようです。

取得する代わりに ちょうど カウント ( スロー 大きなテーブル付き):



SELECT count(*)ASexact_count FROM myschema.mytable;

あなたはこのような近い見積もりを得る( 非常に速い ):

SELECT reltuples :: bigint AS Estimate FROM pg_class where relname = 'mytable';

見積もりがどれだけ近いかは、実行するかどうかによって異なります十分に分析します。通常は非常に近いです。
PostgreSQL WikiFAQを参照してください。
または、count(*)パフォーマンス専用のwikiページ。



さらに良い

PostgreSQLWikiの記事は 少しずさんな 。 1つのデータベース(異なるスキーマ)に同じ名前の複数のテーブルが存在する可能性を無視しました。それを説明するには:

SELECT c.reltuples :: bigint AS Estimate FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relname = 'mytable' AND n.nspname = 'myschema'

またはさらに良い

SELECT reltuples :: bigint AS Estimate FROM pg_class WHERE oid = 'myschema.mytable' :: regclass;

より速く、よりシンプルに、より安全に、よりエレガントに。オブジェクト識別子の種類に関するマニュアルを参照してください。

使用する無効なテーブル名の例外を回避するためのPostgres9.4以降のto_regclass( 'myschema.mytable'):



  • 特定のスキーマにテーブルが存在するかどうかを確認する方法


Postgres 9.5以降のテーブルサンプルシステム(n)

SELECT 100 * count(*)AS見積もりからmytable TABLESAMPLE SYSTEM(1);

@a_horseがコメントしたように、新しく追加された句SELECTコマンドは、統計情報がpg_classは、何らかの理由で十分に最新ではありません。例えば:

  • 番号自動真空実行中。
  • ビッグ直後INSERTまたは消去。
  • TEMPORARYテーブル(自動真空)。

これはランダムに見えるだけです NS %(例の1)ブロックの選択とその中の行のカウント。サンプルが大きくなると、コストが増加し、エラーが減少します。精度はより多くの要因に依存します:

  • 行サイズの分布。特定のブロックがたまたま通常よりも広い行を保持している場合、カウントは通常よりも少なくなります。
  • 死んだタプルまたはFILLFACTORはブロックごとにスペースを占有します。テーブル全体に不均一に分布している場合、見積もりがずれている可能性があります。
  • 一般的な丸めエラー。

ほとんどの場合、pg_classはより速く、より正確になります。

実際の質問への回答

まず、合計数が事前定義された定数よりも大きい場合、そのテーブルの行数を知る必要があります。

そしてそれかどうか...

...カウントが定数値を通過した瞬間に可能ですが、カウントを停止します(そして、行カウントが大きいことを通知するためにカウントが終了するのを待たないでください)。

はい。 あなたは使用することができます とのサブクエリ制限

SELECT count(*)FROM(SELECT 1FROMトークンLIMIT500000)t;

Postgres 実際にカウントを停止します 与えられた制限を超えると、 正確で最新 最大カウント NS 行(例では500000)、および NS それ以外は。の見積もりほど速くはありませんただし、pg_class。


私はこれをpostgresアプリで一度実行しました:

EXPLAIN SELECT * FROM foo;

次に、正規表現または同様のロジックを使用して出力を調べます。単純なSELECT *の場合、出力の最初の行は次のようになります。

uidのシーケンススキャン(コスト= 0.00..1.21行= 8幅= 75)

あなたは使用することができます返される行数の概算としてのrows =( d +)値、次に実際の値のみを実行します見積もりがしきい値の1.5倍未満(またはアプリケーションにとって意味があると思われる数値)である場合は、COUNT(*)を選択します。

クエリの複雑さによっては、この数値の精度が低下する場合があります。実際、私のアプリケーションでは、結合と複雑な条件を追加すると、100の累乗の範囲内で何行が返されるかを知ることさえできず、非常に不正確になり、その戦略を放棄する必要がありました。

ただし、クエリが十分に単純で、Pgがある程度の許容誤差内で返される行数を予測できる場合は、それが機能する可能性があります。


このブログからの参照。

以下を使用して、行数を検索するためのクエリを実行できます。

pg_classの使用:

SELECT reltuples :: bigint AS EstimatedCount FROM pg_class WHERE oid = 'public.TableName' :: regclass;

pg_stat_user_tablesの使用:

SELECT schemaname、relname、n_live_tup AS EstimatedCount FROM pg_stat_user_tables ORDER BY n_live_tup DESC;