큰 테이블 에서 행을 계산하는 것은 PostgreSQL에서 느린 것으로 알려져 있습니다. 정확한 숫자를 얻으려면 MVCC 의 특성으로 인해 전체 행 수를 계산해야합니다 . 귀하의 경우처럼 개수가 정확할 필요 가 없는 경우이를 극적으로 가속화 할 수 있는 방법 이 있습니다.
정확한 개수 를 얻는 대신 ( 큰 테이블에서는 느림 ) :
SELECT count(*) AS exact_count FROM myschema.mytable;
다음과 같은 가까운 추정치를 얻습니다 ( 매우 빠름 ).
SELECT reltuples::bigint AS estimate FROM pg_class where relname='mytable';
추정치가 얼마나 가까운지는 ANALYZE
충분히 실행했는지에 따라 다릅니다 . 일반적으로 매우 가깝습니다. PostgreSQL Wiki FAQ를
참조하십시오 .
또는 count (*) 성능에 대한 전용 위키 페이지 .
더 나은
PostgreSQL의 위키의 문서 되어 있었다 약간의 실수 . 하나의 데이터베이스에 다른 스키마에 같은 이름의 여러 테이블이있을 수 있다는 가능성을 무시했습니다. 이를 설명하려면 :
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;
더 빠르고 간단하고 안전하며 우아합니다. 객체 식별자 유형 에 대한 설명서를 참조하십시오 .
to_regclass('myschema.mytable')
Postgres 9.4 이상에서 사용하면 잘못된 테이블 이름에 대한 예외를 방지 할 수 있습니다.
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;
포스트 그레스는 실제로 계산 중지 , 당신이 얻을 주어진 한계 너머를 정확하고 현재 까지 대한 수를 N 과, (예의 500000) 행을 N 그렇지. pg_class
하지만 의 추정치만큼 빠르지는 않습니다.