답변:
이러한 종류의 카운트를 얻는 방법에는 세 가지가 있으며 각각 고유 한 장단점이 있습니다.
실제 개수를 원하면 각 테이블에 대해 사용한 것과 같은 SELECT 문을 실행해야합니다. PostgreSQL은 행 가시성 정보를 다른 곳이 아닌 행 자체에 유지하므로 정확한 수는 일부 트랜잭션에만 관련 될 수 있기 때문입니다. 트랜잭션이 실행될 때 해당 트랜잭션에 표시되는 개수를 얻습니다. 데이터베이스의 모든 테이블에 대해 실행되도록 자동화 할 수는 있지만 그 정도의 정확도가 필요하지 않거나 오랫동안 기다릴 필요가 있습니다.
두 번째 방법은 통계 수집기가 언제든지 "실제"행 수 (추후 업데이트로 삭제 또는 폐기되지 않음)를 대략적으로 추적합니다. 이 값은 활동이 많을 때 약간 벗어날 수 있지만 일반적으로 좋은 추정치입니다.
SELECT schemaname,relname,n_live_tup
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC;
또한 얼마나 많은 행이 죽었는지 보여줄 수 있습니다.
세 번째 방법은 테이블 통계를 업데이트하기 위해 PostgreSQL 8.3에서 정기적으로 autovacuum 프로세스에 의해 실행되는 시스템 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 내부에서 더 유용한 정보가 있는지 여부에 따라 결정합니다. 기본적인 계산의 목적으로, 일반적으로 큰 것이 얼마나 큰지 알기 위해서는 충분히 정확해야합니다.
n_live_tup
했습니까? Redshift 데이터베이스에 해당 열이 없습니다. Postgres 8.0.2의 파생물입니다.
pg_stat_user_tables
)는 대부분 0을 반환했습니다 . 모든 스키마 / 테이블에서 실행 하고 응답을 영원히 기다리기 보다는 먼저 'third approach'를 사용하여 결과를 확인했으며 (을 사용하여 ) 매우 정확한 수를 반환했습니다. n_live_tup
ANALYZE
ANALYZE
pg_class
각 테이블의 정확한 개수를 얻기 위해 함수가 필요없는 솔루션은 다음과 같습니다.
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에서 카운트 정보를 추출하여 숫자로 변환합니다.
파생 테이블은 실제로 필요하지는 않지만 xpath()
조금 이해하기 쉽게 만듭니다. 그렇지 않으면 전체 query_to_xml()
를 xpath()
함수에 전달해야합니다 .
query_to_jsonb()
.
select count(*)
모든 테이블에서 실행 됩니다.
xpath()
함수는 단일 행 에만 적용됩니다 .count(*)
견적을 얻으려면 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
최신 format()
기능을 사용 하거나 사용 하지 않고 따옴표없이 실행 가능한 SQL에 삽입하면 안됩니다 %I
. 그렇지 않으면 일부 악의적 인 사람이 자신 tablename;DROP TABLE other_table
의 테이블 이름을 테이블 이름으로 완벽하게 사용할 수 있습니다 .
SQL 삽입 및 재미있는 문자 문제가 없어도 테이블 이름은 대소 문자가 다른 변형으로 존재할 수 있습니다. 테이블의 이름은 경우 ABCD
와 다른 하나 abcd
는이 SELECT count(*) FROM...
그렇지 인용 된 이름을 사용해야은 건너 뛸 ABCD
카운트 abcd
를 두 번 누릅니다. %I
형식이 자동으로이 작업을 수행합니다.
information_schema.tables
table_type이 'BASE TABLE'
(!) 인 경우에도 테이블 외에 사용자 정의 복합 유형을 나열합니다 . 결과적으로, 우리는 반복 할 수 없으며 information_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;
ANALYZE
테이블에서 매뉴얼 을 실행하지 않으면 통계가 사라질 수 있습니다. 데이터베이스로드 및 데이터베이스 구성 방법에 대한 질문입니다 (통계가 더 자주 업데이트되면 통계가 더 정확하지만 런타임 성능이 저하 될 수 있음). 궁극적으로 정확한 데이터를 얻는 유일한 방법 select count(*) from table
은 모든 테이블에 대해 실행 하는 것입니다.
헤 로쿠의 느린 행 카운터가 새로 고침 될 때까지 기다릴 수없고 어떤 헤 로쿠 계획이 필요한지를 평가하려는 사람들에게 해킹 된 실질적인 답변 :
기본적으로 당신이 실행하려는 \dt
에서 psql
, (가 같이 표시됩니다 좋아하는 텍스트 편집기로 결과를 복사 :
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
[..]
select '$1', count(*) from $1 union/g
/g
(유지 union
) 해야합니다 ;
. union
세미콜론 앞의 마지막을 제거하는 것을 잊지 마십시오 .
union
세미콜론 전에 것은"나는 :) 의미 명확히하기 위해 "마지막"이라는 단어를 추가 것입니다
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
select count(*) from table_name;
OP 에서 동일하게 요약됩니다 !
나는 보통 통계, 특히 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;
dsql2('select count(*) from livescreen.'||table_name)
자체 기능으로 전환 될 수 있거나 더 좋아 보여야합니다 .
이것을 수집 한 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();
하면 모든 테이블의 행 수를 얻을 수 있습니다.
quote_ident(t_name.relname)
비정상적인 이름 (예 : "column-name")을 올바르게 지원하려면 열 이름 (예 :)을 인용하는 것이 좋습니다 .
SELECT * FROM count_em_all() as r ORDER BY r.num_rows DESC;
간단한 두 단계 :
(참고 : 아무것도 변경할 필요가 없습니다-그냥 붙여 넣기를 복사 하십시오 )
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;
비공개 테이블에도 모든 테이블을 포함하도록 약간 변형했습니다.
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();
그것을 호출하는 데 사용 합니다.
이 유용한 정보를 찾으십시오. 폴
나는 Daniel Vé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"
}
모든 테이블의 합계 + 개수가있는 테이블 목록을 원했습니다. 대부분의 시간이 소요 된 성능 차트와 비슷합니다.
WITH results AS (
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'
GROUP BY schemaname, relname, reltuples
)
SELECT * FROM results
UNION
SELECT 'all' AS schemaname, 'all' AS relname, SUM(reltuples) AS "reltuples" FROM results
ORDER BY reltuples DESC
물론 LIMIT
이 버전의 결과에 대해서도 조항을 추가 할 수 있으므로 n
전체적으로뿐만 아니라 가장 큰 범죄자 를 얻을 수 있습니다.
이것에 대해 주목해야 할 한 가지는 대량 수입 후 잠시 동안 그대로 두어야한다는 것입니다. 실제 가져 오기 데이터를 사용하여 여러 테이블의 데이터베이스에 5000 행을 추가하여 이것을 테스트했습니다. 약 1 분 동안 1800 개의 레코드를 표시했습니다 (아마도 구성 가능한 창).
이것은 https://stackoverflow.com/a/2611745/1548557 작업을 기반으로 하므로 쿼리가 CTE 내에서 사용하도록 감사합니다.
with tbl as (SELECT table_schema,table_name FROM information_schema.tables where table_name not like 'pg_%' and table_schema in ('public')) select table_schema, table_name, (xpath('/row/c/text()', query_to_xml(format('select count(*) as c from %I.%I', table_schema, table_name), false, true, '')))[1]::text::int as rows_n from tbl ORDER BY 3 DESC;