私はPostgresの全てのテーブルの行数を見つける方法を探しています。私は私が一度にこの1つのテーブルをすることができることを知っています:
SELECT count(*) FROM table_name;
しかし、私はすべてのテーブルの行数を見て、それから私のすべてのテーブルがどれくらい大きいかのアイデアを得るためにそれによって注文したいです。
この種のカウントを取得するには3つの方法があり、それぞれ独自のトレードオフがあります。
真のカウントが必要な場合は、各テーブルに対して使用したのと同じようにSELECTステートメントを実行する必要があります。これは、PostgreSQLが行の可視性情報を他の場所ではなく行自体に保持しているため、正確なカウントはトランザクションとの相対関係にしかなり得ないためです。トランザクションが実行された時点でそのトランザクションが何を見ているかがわかります。データベース内のすべてのテーブルに対して実行するようにこれを自動化することはできますが、そのレベルの正確さは必要ないか、それほど長く待つ必要はおそらくないでしょう。
2番目の方法では、統計収集機能は、いつでも大まかに「ライブ」行(削除または後の更新で廃止されていない)がいくつあるかを追跡します。この値は、激しいアクティビティの下では少しずれる可能性がありますが、一般的には良い推定値です。
SELECT schemaname,relname,n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;
それはまた、いくつの行がデッドであるかを示すこともできます。これはそれ自体監視するのに興味深い数字です。
3番目の方法は、PostgreSQL 8.3以降でautovacuumプロセスによって定期的に実行されてテーブル統計を更新するsystem ANALYZEコマンドも行推定値を計算することです。あなたはこのようなものをつかむことができます:
SELECT
nspname AS schemaname,relname,reltuples
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE
nspname NOT IN ('pg_catalog', 'information_schema') AND
relkind='r'
ORDER BY reltuples DESC;
これらのクエリのどちらを使用するのが良いかは言い難いです。通常、私はpg_classの内部でもpg_stat_user_tablesの内部でも使用したいもっと有用な情報があるかどうかに基づいて判断します。基本的なカウントの目的のためだけに、一般的なものの大きさを確認するためには、どちらも十分正確である必要があります。
これは、各テーブルの正確なカウントを得るために関数を必要としない解決策です。
select table_schema,
table_name,
(xpath('/row/cnt/text()', xml_count))[1]::text::int as row_count
from (
select table_name, table_schema,
query_to_xml(format('select count(*) as cnt from %I.%I', table_schema, table_name), false, true, '') as xml_count
from information_schema.tables
where table_schema = 'public' --<< change here for the schema you want
) t
query_to_xml
は渡されたSQLクエリを実行し、結果(そのテーブルの行数)を含むXMLを返します。外側のxpath()
はそのxmlからcount情報を抽出してそれを数に変換します
派生テーブルは必ずしも必要ではありませんが、xpath()
を理解しやすくするために必要です。そうしないと、query_to_xml()
全体をxpath()
関数に渡す必要があります。
見積もりを取得するには、 Greg Smithの答え を参照してください。
正確な数を数えるために、これまでの他の答えはいくつかの問題に悩まされています、それらのいくつかは深刻です(下記参照)。これがうまくいけばいいバージョンです。
CREATE FUNCTION rowcount_all(schema_name text default 'public')
RETURNS table(table_name text, cnt bigint) as
$$
declare
table_name text;
begin
for table_name in SELECT c.relname FROM pg_class c
JOIN pg_namespace s ON (c.relnamespace=s.oid)
WHERE c.relkind = 'r' AND s.nspname=schema_name
LOOP
RETURN QUERY EXECUTE format('select cast(%L as text),count(*) from %I.%I',
table_name, schema_name, table_name);
END LOOP;
end
$$ language plpgsql;
パラメータとしてスキーマ名を取ります。パラメータが指定されていない場合はpublic
を取ります。
関数を変更せずにスキーマの特定のリストまたはクエリから取得したリストを操作するには、次のようにクエリ内から呼び出すことができます。
WITH rc(schema_name,tbl) AS (
select s.n,rowcount_all(s.n) from (values ('schema1'),('schema2')) as s(n)
)
SELECT schema_name,(tbl).* FROM rc;
これにより、スキーマ、テーブル、および行数を含む3列の出力が生成されます。
これが、この関数が回避する他の答えの中のいくつかの問題です。
テーブル名とスキーマ名は、quote_ident
またはその%I
フォーマット文字列を含む最新のformat()
関数を使用して、引用符なしで実行可能SQLにインジェクトすることはできません。そうでなければ、悪意のある人が自分のテーブルにtablename;DROP TABLE other_table
という名前を付けることがあり、これは完全にテーブル名として有効です。
SQLインジェクションや変な文字の問題がなくても、テーブル名は大文字と小文字が異なるバリアントで存在する可能性があります。テーブルの名前がABCD
で、別のテーブルの名前がabcd
である場合、SELECT count(*) FROM...
は引用符で囲まれた名前を使用する必要があります。それ以外の場合、ABCD
をスキップしてabcd
を2回カウントします。 %I
of formatはこれを自動的に行います。
information_schema.tables
は、table_typeが'BASE TABLE'
(!)の場合でも、テーブルに加えてカスタム複合型をリストします。結果として、oninformation_schema.tables
を繰り返すことはできません、そうでなければselect count(*) from name_of_composite_type
を持つ危険性があり、それは失敗するでしょう。 OTOHのpg_class where relkind='r'
は常にうまくいくはずです。
COUNT()の型はbigint
ではなくint
です。 21.5億行を超えるテーブルが存在する可能性があります(ただし、カウント(*)を実行することはお勧めできません)。
関数が複数の列を持つ結果セットを返すためには、永続型を作成する必要はありません。 RETURNS TABLE(definition...)
はより良い代替手段です。
古くなってしまう可能性があるデータを気にしないのであれば、 クエリオプティマイザで使用されているのと同じ統計にアクセスできます 。
何かのようなもの:
SELECT relname, n_tup_ins - n_tup_del as rowcount FROM pg_stat_all_tables;
どのHerokuのプランが必要かを評価しようとしていて、herokuの遅いローカウンタがリフレッシュされるのを待つことができない人々のための、ハックで実用的な答え:
基本的にあなたはpsql
で\dt
を実行したい、あなたの好きなテキストエディタに結果をコピーしなさい(それはこのように見えるでしょう:
public | auth_group | table | axrsosvelhutvw
public | auth_group_permissions | table | axrsosvelhutvw
public | auth_permission | table | axrsosvelhutvw
public | auth_user | table | axrsosvelhutvw
public | auth_user_groups | table | axrsosvelhutvw
public | auth_user_user_permissions | table | axrsosvelhutvw
public | background_task | table | axrsosvelhutvw
public | Django_admin_log | table | axrsosvelhutvw
public | Django_content_type | table | axrsosvelhutvw
public | Django_migrations | table | axrsosvelhutvw
public | Django_session | table | axrsosvelhutvw
public | exercises_assignment | table | axrsosvelhutvw
次に、正規表現検索を実行し、次のように置き換えます。
^[^|]*\|\s+([^|]*?)\s+\| table \|.*$
に:
select '\1', count(*) from \1 union/g
これはあなたにこれに非常に類似した何かをもたらすでしょう:
select 'auth_group', count(*) from auth_group union
select 'auth_group_permissions', count(*) from auth_group_permissions union
select 'auth_permission', count(*) from auth_permission union
select 'auth_user', count(*) from auth_user union
select 'auth_user_groups', count(*) from auth_user_groups union
select 'auth_user_user_permissions', count(*) from auth_user_user_permissions union
select 'background_task', count(*) from background_task union
select 'Django_admin_log', count(*) from Django_admin_log union
select 'Django_content_type', count(*) from Django_content_type union
select 'Django_migrations', count(*) from Django_migrations union
select 'Django_session', count(*) from Django_session
;
(union
を削除し、最後にセミコロンを手動で追加する必要があります)
psql
で実行すれば完了です。
?column? | count
--------------------------------+-------
auth_group_permissions | 0
auth_user_user_permissions | 0
Django_session | 1306
Django_content_type | 17
auth_user_groups | 162
Django_admin_log | 9106
Django_migrations | 19
[..]
bash の答えがあなたに受け入れられるかどうかわからないが、FWIW ...
PGCOMMAND=" psql -h localhost -U fred -d mydb -At -c \"
SELECT table_name
FROM information_schema.tables
WHERE table_type='BASE TABLE'
AND table_schema='public'
\""
TABLENAMES=$(export PGPASSWORD=test; eval "$PGCOMMAND")
for TABLENAME in $TABLENAMES; do
PGCOMMAND=" psql -h localhost -U fred -d mydb -At -c \"
SELECT '$TABLENAME',
count(*)
FROM $TABLENAME
\""
eval "$PGCOMMAND"
done
特にPostgreSQLでは、私は通常統計に頼りません。
SELECT table_name, dsql2('select count(*) from '||table_name) as rownum
FROM information_schema.tables
WHERE table_type='BASE TABLE'
AND table_schema='livescreen'
ORDER BY 2 DESC;
CREATE OR REPLACE FUNCTION dsql2(i_text text)
RETURNS int AS
$BODY$
Declare
v_val int;
BEGIN
execute i_text into v_val;
return v_val;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
これを収集した場所のURLは覚えていません。しかし、これが役に立つことを願っています:
CREATE TYPE table_count AS (table_name TEXT, num_rows INTEGER);
CREATE OR REPLACE FUNCTION count_em_all () RETURNS SETOF table_count AS '
DECLARE
the_count RECORD;
t_name RECORD;
r table_count%ROWTYPE;
BEGIN
FOR t_name IN
SELECT
c.relname
FROM
pg_catalog.pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE
c.relkind = ''r''
AND n.nspname = ''public''
ORDER BY 1
LOOP
FOR the_count IN EXECUTE ''SELECT COUNT(*) AS "count" FROM '' || t_name.relname
LOOP
END LOOP;
r.table_name := t_name.relname;
r.num_rows := the_count.count;
RETURN NEXT r;
END LOOP;
RETURN;
END;
' LANGUAGE plpgsql;
select count_em_all();
を実行すると、すべてのテーブルの行数が得られます。
非公開テーブルについても、すべてのテーブルを含めるように少しバリエーションを作りました。
CREATE TYPE table_count AS (table_schema TEXT,table_name TEXT, num_rows INTEGER);
CREATE OR REPLACE FUNCTION count_em_all () RETURNS SETOF table_count AS '
DECLARE
the_count RECORD;
t_name RECORD;
r table_count%ROWTYPE;
BEGIN
FOR t_name IN
SELECT table_schema,table_name
FROM information_schema.tables
where table_schema !=''pg_catalog''
and table_schema !=''information_schema''
ORDER BY 1,2
LOOP
FOR the_count IN EXECUTE ''SELECT COUNT(*) AS "count" FROM '' || t_name.table_schema||''.''||t_name.table_name
LOOP
END LOOP;
r.table_schema := t_name.table_schema;
r.table_name := t_name.table_name;
r.num_rows := the_count.count;
RETURN NEXT r;
END LOOP;
RETURN;
END;
' LANGUAGE plpgsql;
呼び出すにはselect count_em_all();
を使います。
あなたがこれが役に立つことを願っています。ポール
簡単な2つのステップ:
(注:何も変更する必要はありません - コピーするだけでコピーできます)
1。関数を作成する
create function
cnt_rows(schema text, tablename text) returns integer
as
$body$
declare
result integer;
query varchar;
begin
query := 'SELECT count(1) FROM ' || schema || '.' || tablename;
execute query into result;
return result;
end;
$body$
language plpgsql;
2。このクエリを実行して、すべてのテーブルの行数を取得します
select sum(cnt_rows) as total_no_of_rows from (select
cnt_rows(table_schema, table_name)
from information_schema.tables
where
table_schema not in ('pg_catalog', 'information_schema')
and table_type='BASE TABLE') as subq;
または
行数を表単位で取得するには
select
table_schema,
table_name,
cnt_rows(table_schema, table_name)
from information_schema.tables
where
table_schema not in ('pg_catalog', 'information_schema')
and table_type='BASE TABLE'
order by 3 desc;
DanielVéritéの 答え が好きです。しかし、CREATEステートメントを使用できないときは、 bashソリューション を使用するか、Windowsユーザーの場合はPowerShellソリューションを使用できます。
# You don't need this if you have pgpass.conf
$env:PGPASSWORD = "userpass"
# Get table list
$tables = & 'C:\Program Files\PostgreSQL\9.4\bin\psql.exe' -U user -w -d dbname -At -c "select table_name from information_schema.tables where table_type='BASE TABLE' AND table_schema='schema1'"
foreach ($table in $tables) {
& 'C:\path_to_postresql\bin\psql.exe' -U root -w -d dbname -At -c "select '$table', count(*) from $table"
}
これは私のために働きました
SELECT schemaname、relname、n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC;