Postgres의 모든 테이블에 대한 행 수를 찾는 방법을 찾고 있습니다. 나는이 테이블을 한 번에 하나씩 할 수 있다는 것을 알고있다.
SELECT count(*) FROM table_name;
그러나 모든 테이블의 행 수를 확인한 다음 순서대로 정렬하여 내 모든 테이블의 크기를 알 수 있습니다.
답변
이러한 종류의 카운트를 얻는 방법에는 세 가지가 있으며 각각 고유 한 장단점이 있습니다.
실제 개수를 원하면 각 테이블에 대해 사용한 것과 같은 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 내부에서 더 유용한 정보가 있는지 여부에 따라 결정합니다. 기본적인 계산의 목적으로, 일반적으로 큰 것이 얼마나 큰지 알기 위해서는 충분히 정확해야합니다.
답변
각 테이블의 정확한 개수를 얻기 위해 함수가 필요없는 솔루션은 다음과 같습니다.
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()
함수에 전달해야합니다 .
답변
견적을 얻으려면 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
있으며 실패 할 것입니다. OTOHpg_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;
답변
헤 로쿠의 느린 행 카운터가 새로 고침 될 때까지 기다릴 수없고 어떤 헤 로쿠 계획이 필요한지를 평가하려는 사람들에게 해킹 된 실질적인 답변 :
기본적으로 당신이 실행하려는 \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
[..]
답변
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;