sql >> データベース >  >> RDS >> PostgreSQL

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

    PostgreSQLでは、大きなテーブルの行を数えるのが遅いことが知られています。 MVCCモデルでは、正確な数のライブ行を完全にカウントする必要があります。 これを劇的にスピードアップするための回避策があります カウントがない場合 正確である必要があります あなたの場合のようです。

    (「正確な」カウントでさえ、到着時に死んでいる可能性があることを忘れないでください!)

    正確な数

    遅い 大きなテーブルの場合。
    同時書き込み操作では、取得した瞬間に古くなる可能性があります。

    SELECT count(*) AS exact_count FROM myschema.mytable;
    
    見積もり

    非常に速い

    SELECT reltuples AS estimate FROM pg_class where relname = 'mytable';
    

    通常、見積もりは非常に近いです。どれだけ近いかは、ANALYZEかどうかによって異なります またはVACUUM 十分に実行されている-「十分」は、テーブルへの書き込みアクティビティのレベルによって定義されます。

    より安全な見積もり

    上記は、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';
    

    bigintへのキャスト realをフォーマットします 特に大きなカウントの場合は、うまく数えます。

    より良い見積もり

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

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

    'myschema.mytable'::regclassを置き換えます to_regclass('myschema.mytable')を使用 Postgres 9.4以降では、無効なテーブル名の例外の代わりに何も取得しません。参照:

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

    さらに良い見積もり(追加コストはごくわずかです)

    Postgresプランナーが行うことを実行できます。 行推定の例の引用 マニュアルの内容:

    これらの番号は、最後のVACUUMの時点で最新のものです。 またはANALYZE テーブルの上。次に、プランナはテーブル内の実際の現在のページ数をフェッチします(これは安価な操作であり、テーブルスキャンを必要としません)。それがrelpagesと異なる場合 次にreltuples それに応じてスケーリングされ、現在の行数の見積もりに到達します。

    Postgresはestimate_rel_sizeを使用します src/backend/utils/adt/plancat.cで定義されています 、pg_classにデータがない場合のコーナーケースもカバーしています 関係が決して真空にされなかったので。 SQLでも同様のことができます:

    最小形式

    SELECT (reltuples / relpages * (pg_relation_size(oid) / 8192))::bigint
    FROM   pg_class
    WHERE  oid = 'mytable'::regclass;  -- your table here
    

    安全で明示的

    SELECT (CASE WHEN c.reltuples < 0 THEN NULL       -- never vacuumed
                 WHEN c.relpages = 0 THEN float8 '0'  -- empty table
                 ELSE c.reltuples / c.relpages END
          * (pg_relation_size(c.oid) / pg_catalog.current_setting('block_size')::int)
           )::bigint
    FROM   pg_class c
    WHERE  c.oid = 'myschema.mytable'::regclass;      -- schema-qualified table here
    

    空のテーブルやVACUUMを見たことがないテーブルで壊れることはありません またはANALYZEpg_classのマニュアル :

    テーブルがまだバキュームまたは分析されていない場合は、reltuples -1が含まれています 行数が不明であることを示します。

    このクエリがNULLを返す場合 、ANALYZEを実行します またはVACUUM テーブルのために繰り返します。 (または、Postgresのように列タイプに基づいて行幅を見積もることもできますが、これは面倒でエラーが発生しやすくなります。)

    このクエリが0を返す場合 、テーブルが空のようです。しかし、私はANALYZE 確かめる。 (そして多分あなたのautovacuumをチェックしてください 設定。)

    通常、block_size は8192です。current_setting('block_size')::int まれな例外をカバーしています。

    テーブルとスキーマの資格により、search_pathの影響を受けなくなります。 とスコープ。

    いずれにせよ、クエリは一貫して<0.1ミリ秒かかります。

    その他のWebリソース:

    • Postgres Wiki FAQ
    • カウントの見積もりとcount(*)のパフォーマンスに関するPostgreswikiページ

    TABLESAMPLE SYSTEM (n) Postgres9.5以降

    SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);
    

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

    • autovacuumはありません 実行中。
    • 大きなINSERTの直後 / UPDATE / DELETE
    • TEMPORARY テーブル(autovacuumの対象外) 。

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

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

    通常、pg_classからの見積もり より速く、より正確になります。

    実際の質問への回答

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

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

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

    はい。 LIMITサブクエリを使用できます

    SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;
    

    Postgres実際にはカウントを停止します 指定された制限を超えると、正確で最新のが得られます 最大nまでカウント 行(例では500000)、および n そうでなければ。 pg_classの見積もりほど速くはありません 、しかし。



    1. c#を使用してSQL Serverテーブルの変更を監視するにはどうすればよいですか?

    2. MariaDBでのSEC_TO_TIME()のしくみ

    3. 配列タイプのarray_agg

    4. .sqlファイルpostgresの画面に印刷