38

PostgreSQLテーブルの行数を数える必要があります。この場合、条件が満たされる必要はありません。クエリ速度が大幅に向上した場合は、行の見積もりを取得することは完全に許容されます。

基本的に、select count(id) from <table>正確な結果が得られないことを意味する場合でも、できるだけ速く実行したいと考えています。

4

6 に答える 6

63

非常に迅速な見積もりの​​場合:

SELECT reltuples FROM pg_class WHERE relname = 'my_table';

ただし、いくつかの注意点があります。1つは、relnameで必ずしも一意ではありませんpg_classrelnameデータベースの複数のスキーマに同じテーブルが複数存在する可能性があります。明確にするために:

SELECT reltuples::bigint FROM pg_class WHERE oid = 'my_schema.my_table'::regclass;

テーブル名をスキーマ修飾しない場合、キャストregclassは現在を監視しsearch_pathて最適なものを選択します。また、テーブルがのどのスキーマにも存在しない(または表示されない)search_path場合は、エラーメッセージが表示されます。マニュアルのオブジェクト識別子タイプを参照してください。

特に大きなカウントの場合、数値を適切にbigintフォーマットするためのキャスト。real

また、reltuples多かれ少なかれ時代遅れになる可能性があります。これをある程度補う方法があります。新しく改善されたオプションを使用して、この後の回答を参照してください。

また、クエリpg_stat_user_tablesは何倍も遅くなります(ただし、フルカウントよりもはるかに高速です)。これは、いくつかのテーブルのビューであるためです。

于 2013-01-28T21:53:35.743 に答える
13

大きなテーブルの場合はカウントが遅いため、次の方法で詳細な見積もりを取得できます。

SELECT reltuples::bigint AS estimate 
FROM pg_class 
WHERE relname='tableName';

そして、その非常に高速な結果は変動しませんが、それでも厳密な見積もりです。

  • reltuplespg_classテーブルの列であり、「テーブルの行数。これはプランナーが使用する推定値にすぎません。VACUUM、ANALYZE、およびCREATE INDEXなどのいくつかのDDLコマンドによって更新されます」(手動)
  • カタログpg_classは、テーブルと、列があるか、テーブルに類似している他のほとんどすべてをカタログ化します。これには、インデックス(ただし、pg_indexも参照)、シーケンス、ビュー、複合型、およびいくつかの種類の特別な関係(手動)が含まれます。
  • 「「SELECTcount(*)FROM bigtable;」が遅いのはなぜですか?」:http ://wiki.postgresql.org/wiki/FAQ#Why_is_.22SELECT_count.28.2A.29_FROM_bigtable.3B.22_slow.3F
于 2013-01-28T20:31:46.320 に答える
6

インデックス付きフィールド(できれば「id」)でCOUNT()を実行する以外に、次善の策は、INSERTのトリガーを使用して実際に行数をテーブルにキャッシュすることです。当然、代わりにキャッシュをチェックします。

概算として、これを試すことができます(https://wiki.postgresql.org/wiki/Count_estimateから):

select reltuples from pg_class where relname='tablename';
于 2013-01-28T20:28:57.793 に答える
3

INSERTまたはDELETEの後にトリガーを使用するだけで、テーブル内のカウントの正確な値を要求できます。

CREATE TABLE  tcounter(id serial primary key,table_schema text, table_name text, count serial);

insert into tcounter(table_schema, table_name,count) select 'my_schema', 'my_table', count(*) from my_schema.my_table;

トリガーを使用します

CREATE OR REPLACE FUNCTION ex_count()
RETURNS trigger AS
$BODY$
BEGIN
    IF (TG_OP='INSERT') THEN
      UPDATE tcounter set count = count + 1 where table_schema = TG_TABLE_SCHEMA::TEXT and table_name = TG_TABLE_NAME::TEXT;
    ELSIF  (TG_OP='DELETE') THEN
      UPDATE tcounter set count = count - 1 where table_schema = TG_TABLE_SCHEMA::TEXT and table_name = TG_TABLE_NAME::TEXT;
    END IF;
RETURN NEW;
END$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;

CREATE TRIGGER tg_counter  AFTER INSERT OR DELETE
  ON my_schema.my_table  FOR EACH ROW  EXECUTE PROCEDURE ex_count();

そしてカウントを求める

select * from tcounter where table_schema =  'my_schema' and table_name = 'my_table'

これは、最初のレコードを初期化するためにcount(*)を1回選択することを意味します

于 2015-01-29T15:56:58.477 に答える
2

システムテーブル「pg_stat_user_tables」から見積もりを取得できます。

select schemaname, relname, n_live_tup 
from pg_stat_user_tables 
where schemaname = 'your_schema_name'
and relname = 'your_table_name';
于 2013-01-28T20:33:57.250 に答える
0

データベースが小さい場合は、@mike-sherrill-cat-recallのようなすべてのテーブルの見積もりを取得できます。ただし、このコマンドはすべてのテーブルを一覧表示します。

SELECT schemaname,relname,n_live_tup 
FROM pg_stat_user_tables 
ORDER BY n_live_tup DESC;

出力は次のようになります。

 schemaname |      relname       | n_live_tup
------------+--------------------+------------
 public     | items              |      21806
 public     | tags               |      11213
 public     | sessions           |       3269
 public     | users              |        266
 public     | shops              |        259
 public     | quantities         |         34
 public     | schema_migrations  |         30
 public     | locations          |          8
(8 rows)
于 2016-12-18T18:49:19.173 に答える