PostgreSQL 쿼리가 얼마나 멀리 있는지 어떻게 알 수 있습니까?


35

내 SELECT ... INTO 쿼리가 실제로 처리 할 행 수를 알 수 있습니다 (예 : 실현할 행 수를 알고 있습니다).

Postgres가 완료율을 알려주지 않는다는 것을 이해합니다. 로그, 시스템 테이블 등에서 깊이 묻혀서 대상 테이블에 펌핑되거나 SELECT 쿼리로 읽은 행 수를 알 수있는 방법이 있습니까? ?

답변:


33

Daniel Vérité가 언급했듯이 일반적인 해결책은없는 것 같습니다. 파일에서 테이블로 데이터를로드 할 때 다음 기술을 사용하여로드 진행률을 확인할 수 있습니다.

복사 명령 콘솔 진행률 표시 줄

빈 테이블을 만듭니다.

CREATE TABLE mytest (n int);

테이블에로드 할 천만 줄의 데이터 파일을 만듭니다.

$ seq 10000000 > /tmp/data.txt

파일에서 테이블로 데이터를로드하고 진행률 표시 줄을 표시하십시오.

$ pv /tmp/data.txt | psql -c "COPY mytest FROM STDIN;"

데모

여기에 이미지 설명을 입력하십시오

작동 원리

복사 명령 STDIN 옵션을 사용하여 다른 프로세스에서 복사 작업을위한 데이터를 공급할 수 있습니다. pv 명령은 파일을 출력하고 진행률 표시 줄, ETA, 총 경과 시간 및 데이터 전송률을 표시하여 진행 상황을 추적합니다.

COPY 명령 그래픽 진행 표시 줄

동일한 일반적인 기술을 사용하여 그래픽 응용 프로그램이나 웹 기반 응용 프로그램에 진행률 표시 줄을 표시 할 수 있습니다. 예를 들어 psycopg2 모듈을 사용하면 원하는 파일 객체로 복사 명령을 호출 할 수 있습니다. 그런 다음 읽은 파일 객체의 양을 추적하고 진행률 표시 줄을 표시 할 수 있습니다.


2
나는 pv이전에 명령을 보지 못했고 기본적으로 데비안 서버에 설치되지 않았지만 저장소에 있습니다. 설명에 따르면 "pv (파이프 뷰어)를 두 프로세스 사이의 일반 파이프 라인에 삽입하여 데이터가 얼마나 빨리 전달되는지 시각적으로 표시 할 수 있습니다"라고 말합니다. 매우 유용한 명령입니다!
Richard Turner

27

일반적으로 지원되는 방법은 없지만 제한된 컨텍스트에서 개별 쿼리의 진행률을 평가하는 데 사용할 수있는 몇 가지 트릭이 있습니다. 다음은 그중 일부입니다.

시퀀스

SELECT 또는 UPDATE 쿼리에 any가 포함되어 nextval(sequence_name)있거나 INSERT에 nextval기본값으로 대상 열이있는 경우을 사용하여 다른 세션에서 현재 시퀀스 값을 반복적으로 쿼리 할 수 ​​있습니다 SELECT sequence_name.last_value. 시퀀스는 트랜잭션에 의해 제한되지 않기 때문에 작동합니다. 실행 계획이 쿼리 중에 시퀀스가 ​​선형으로 증가하도록하는 경우 진행률 표시기로 사용할 수 있습니다.

pgstattuple

pgstattuple에 있는 contrib 모듈은 데이터 페이지에서 직접 엿볼 수있는 기능을 제공합니다. 튜플이 빈 테이블에 삽입되었지만 아직 커밋되지 않은 dead_tuple_count경우 pgstattuple함수 의 필드에서 계산됩니다 .

9.1 데모 : 빈 테이블 만들기

CREATE TABLE tt AS (n numeric);

여기에 10M 행을 삽입합시다 :

INSERT INTO tt SELECT * FROM random() from generate_series(1,10000000);

다른 세션에서 삽입하는 동안 매초마다 pgstattuple을 확인하십시오.

$ while true;
   do psql -Atc "select dead_tuple_count from pgstattuple('tt')";
   sleep 1;
  done

결과 :

0
69005
520035
1013430
1492210
1990415
2224625
2772040
3314460
3928660
4317345
4743770
5379430
6080950
6522915
7190395
7953705
8747725
9242045
0

인서트가 완료되면 0으로 돌아갑니다 (모든 튜플이 표시되고 활성화 됨).

이 트릭은 테이블을 새로 만들지 않은 경우에도 사용할 수 있지만 초기 값 dead_tuple_count은 0이 아닌 값일 수 있으며 autovacuum과 같은 다른 쓰기 작업이 진행중인 경우에도 동시에 변경 될 수 있습니다 (어쩌면? autovacuum으로 예상되는 동시성).

그러나 테이블이 명령문 자체 ( CREATE TABLE ... AS SELECT또는 SELECT * INTO newtable)로 작성되면 작성이 처리 되므로 사용할 수 없습니다 . 해결 방법은 행이없는 테이블을 작성하고 (add LIMIT 0) 다음 트랜잭션에서 채우는 것입니다.

참고 pgstattuple가 모든 호출에 전체 테이블을 스캔 : 무료되지 않습니다. 또한 수퍼 유저로 제한됩니다.

맞춤 카운터

Pavel Stehule의 블로그 에서 C로 구현 된 카운터 기능 을 제공하여 지정된 실행 횟수에서 알림을 발생시킵니다. 어떻게 든 함수를 쿼리와 결합하여 실행자가 호출하도록해야합니다. 알림은 쿼리 중에 전송되며 별도의 세션이 필요하지 않으며이를 표시하는 SQL 클라이언트 만 있습니다 ( psql명확한 후 보임).

INSERT INTO의 예는 통지를 올리기 위해 재 작업되었습니다.

/* transformation */
INSERT INTO destination_table
   SELECT (r).*
  FROM (SELECT counter(to_destination_table(_source), 1000, true) r
           FROM source _source) x

함수에 대한 stackoverflow 관련 질문 :
오래 실행되는 PostgreSQL 함수에서 클라이언트로 진행 상황을보고하는 방법

향후 옵션?

2017 년 5 월부터 개발자 커뮤니티에 제출 된 유망한 패치가 있습니다. [PATCH v2] 장기 실행 SQL 쿼리의 진행을 모니터링하는 진행 명령

PostgreSQL 11 이상에서 일반적인 솔루션으로 끝날 수 있습니다. 진행중인 작업 기능에 참여하고 싶은 사용자는 최신 버전의 패치를 적용하고 제안 된 PROGRESS명령을 시도 할 수 있습니다.


3

@AmirAliAkbari가 답변에서 언급했듯이 진행 보고서 기능이 확장되지 않을 때까지 OS 수준의 해결 방법이 있습니다.

이것은 Linux에서만 작동하지만 모든 운영 체제에 대해 쉽게 해결할 수있는 유사한 솔루션이있을 수 있습니다.

그 백엔드를 모두 사용하여 간단한 단일 스레드 프로세스 것을 가장 큰 장점와의 PostgreSQL도 단점 lseek(), read()그리고 write()그들이 공유 MEM 및 잠금에 상호 작용하는 동안, 자신의 테이블 파일을 조작 할 수 있습니다.

결과적으로 모든 백엔드 프로세스는 항상 단일 쿼리에서 작동하며 쉽게 찾을 수 있고 쉽게 찾을 수 있습니다 strace. d.

먼저 다음에서 백엔드 PID를 볼 수 있습니다 SELECT * FROM pg_stat_activity;.

29805270 | dbname  | 20019 |    16384 | username  |                  |             |                 |          -1 | 2018-09-19 21:31:57.68234+02  | 2018-09-19 21:31:59.435376+02 | 2018-09-\
20 00:34:30.892382+02 | 2018-09-20 00:34:30.892386+02 | Client          | ClientRead | active              |       92778 |        92778 |  INSERT INTO ...something...

세 번째 열은 pid입니다. PostgreSQL에서는 백엔드의 Linux 프로세스 pid와 동일합니다.

다음으로, 예를 들어 strace -p 20019 -s 8192:로 추적 할 수 있습니다 ( -s 8192postgresql이 8192 바이트 길이의 블록에서 작동하기 때문에 유용합니다).

sendto(10, "C\0\0\0\17INSERT 0 1\0Z\0\0\0\5T", 22, 0, NULL, 0) = 22
recvfrom(10, "Q\0\0\1\267 INSERT <removed by @peterh>", 8192, 0, NULL, NULL) = 440
sendto(10, "C\0\0\0\17INSERT 0 1\0Z\0\0\0\5T", 22, 0, NULL, 0) = 22
lseek(298, 343634345)...
read(298, "<block data which was read in>"....
write(298, "<block data which was written out>"...

의미 :

  • sendto백엔드가 클라이언트에게 무언가에 응답하면 발생합니다. 이 예에서는 INSERT쿼리 결과에 응답합니다 .
  • recvfrom백엔드가 클라이언트에서 무언가를 얻는 경우 발생합니다. 이 예제에서는 일반적으로 새 쿼리이지만 다른 쿼리 INSERT입니다.
  • lseek 백엔드 스위치가 테이블 파일에서 위치하는 경우 발생합니다.
  • read 백엔드가 테이블 파일에서 블록을 읽는 경우 발생합니다.
  • write 백엔드가 블록을 테이블 파일에 쓰면 발생합니다.

read및 의 경우 write표에서 해당 블록의 내용을 볼 수도 있습니다. 이해하는 데 도움이 될 수 있습니다.

의 경우 recvfrom백엔드의 실제 쿼리를 볼 수 있습니다.


2

다른 답변에서 말했듯이 현재 진행 상황을 일반적으로보고하는 직접적인 방법은 없습니다.

PostgreSQL은 명령 실행 중 특정 명령의 진행 상황을보고 할 수 있습니다. 현재 진행률보고를 지원하는 유일한 명령은 VACUUM입니다. 향후 확장 될 수 있습니다.

때마다 그러나, 9.6에서 시작, VACUUM실행되면, pg_stat_progress_vacuum뷰는 현재 진공 청소기 (자동 진공 작업자 프로세스 포함) 각 백엔드에 대한 하나의 행이 포함됩니다. 자세한 내용은 pg_stat_progress_vacuum설명서에서 찾을 수 있습니다. 27.4 진행률보고 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.