パーセンテージを計算するには、テーブル内の行数を知る必要があります。合計カウントが定義済みの定数よりも大きい場合、定数値を使用します。それ以外の場合は、実際の行数を使用します。
SELECT count(*) FROM table
を使用できます。しかし、定数値が500,0で、テーブルに5,000,000,0行がある場合、すべての行をカウントすると多くの時間が無駄になります。
定数値を超えるとすぐにカウントを停止できますか?
指定された制限を下回っている場合にのみ、正確な行数が必要です。それ以外の場合、カウントが制限を超えている場合は、代わりに制限値を使用し、できるだけ早く答えを求めます。
このようなもの:
SELECT text,count(*), percentual_calculus()
FROM token
GROUP BY text
ORDER BY count DESC;
bigテーブルの行のカウントは、PostgreSQLでは遅いことが知られています。正確な数を取得するには、 [〜#〜] mvcc [〜#〜] の性質により、行を完全にカウントする必要があります。 これを劇的にスピードアップする方法がありますカウントが not でなければならない場合 exact あなたの場合のようです。
exactカウント(大きなテーブルでは slow )を取得する代わりに:
_SELECT count(*) AS exact_count FROM myschema.mytable;
_
次のような近い見積もりが得られます( extremely fast ):
_SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
_
見積もりがどれだけ近いかは、 ANALYZE
で十分かどうかによって異なります。それは通常非常に近いです。
PostgreSQL Wiki FAQ をご覧ください。
または count(*)パフォーマンス専用のwikiページ 。
PostgreSQL Wikiの記事 は 少しずさんなでした。異なるスキーマにある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;
_
より速く、よりシンプルに、より安全に、よりエレガントに。 Object Identifier Types のマニュアルを参照してください。
Postgres 9.4以降でto_regclass('myschema.mytable')
を使用して、無効なテーブル名の例外を回避します。
TABLESAMPLE SYSTEM (n)
Postgres 9.5以降_SELECT 100 * count(*) AS estimate FROM mytable TABLESAMPLE SYSTEM (1);
_
@ a_horse commented のように、SELECT
コマンドに新たに追加された句は、何らかの理由で_pg_class
_の統計が十分に最新でない場合に便利です。例えば:
autovacuum
は実行されていません。INSERT
またはDELETE
の直後。TEMPORARY
テーブル(autovacuum
でカバーされない)。これは、ランダムなn%(例では_1
_)ブロックの選択のみを調べ、その中の行をカウントします。サンプルを大きくすると、コストが増加し、選択の誤りが減ります。精度はより多くの要因に依存します。
FILLFACTOR
はブロックごとにスペースを占有します。テーブル全体に不均一に分布している場合、推定値がオフになる可能性があります。ほとんどの場合、_pg_class
_からの推定はより速く、より正確になります。
最初に、合計カウントが定義済みの定数よりも大きい場合、そのテーブルの行数を知る必要があります。
そしてそれかどうか...
...カウントが定数値を通過した時点で可能です。カウントを停止します(そして、カウントが終了して行カウントが大きいことを知らせるのを待ちません)。
はい。サブクエリをLIMIT
とともに使用できます。
_SELECT count(*) FROM (SELECT 1 FROM token LIMIT 500000) t;
_
Postgres 実際にカウントを停止する指定された制限を超えると、正確で現在最大n行(例では500000)までのカウントを取得し、 nそれ以外の場合。ただし、_pg_class
_の推定ほど高速ではありません。
私はこれをpostgresアプリで1回実行しました:
_EXPLAIN SELECT * FROM foo;
_
次に、正規表現または同様のロジックで出力を調べます。単純なSELECT *の場合、出力の最初の行は次のようになります。
_Seq Scan on uids (cost=0.00..1.21 rows=8 width=75)
_
返される行数のおおよその推定値としてrows=(\d+)
値を使用し、推定値がたとえば1.5x未満の場合にのみ実際のSELECT COUNT(*)
を実行できますしきい値(または、アプリケーションにとって意味があると思われる数値)。
クエリの複雑さに応じて、この数はますます正確でなくなる可能性があります。実際、私のアプリケーションでは、結合と複雑な条件を追加すると、非常に不正確になり、100の累乗内で何行返されるかを知ることすらまったく価値がなくなったため、その戦略を放棄する必要がありました。
ただし、Pgが妥当なエラーの範囲内で返す行数を予測できるほど単純なクエリであれば、それが機能する可能性があります。
以下のクエリ(*または列名なし)でカウントを取得できます。
select from table_name;
Oracleでは、rownum
を使用して、返される行の数を制限できます。他のSQLにも同様の構造が存在すると推測しています。したがって、指定した例では、返される行の数を500001に制限し、count(*)
を適用することができます。
SELECT (case when cnt > 500000 then 500000 else cnt end) myCnt
FROM (SELECT count(*) cnt FROM table WHERE rownum<=500001)
テキスト列の幅はどれくらいですか?
GROUP BYでは、データスキャン(少なくともインデックススキャン)を回避するためにできることはあまりありません。
私はお勧めします:
可能であれば、スキーマを変更してテキストデータの重複を削除します。この方法では、「多数」テーブルの狭い外部キーフィールドでカウントが発生します。
または、テキストのハッシュで生成された列を作成し、ハッシュ列でGROUP BYを作成します。繰り返しますが、これはワークロードを減らすためです(狭い列インデックスをスキャンします)
編集:
元の質問は編集内容と完全には一致しませんでした。 COUNTをGROUP BYで使用すると、テーブル全体のアイテム数ではなく、グループごとのアイテム数が返されることを認識しているかどうかわかりません。
以下を使用して、行カウントを見つけるためにクエリを実行できます。
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;