문제

저는 3개의 인덱스가 있는 2억 5천만 개의 행이 포함된 테이블에서 UPDATE를 실행했습니다.';이 업데이트는 3천만 개의 행을 포함하는 다른 테이블을 사용합니다.현재 약 36시간 동안 실행되고 있습니다.나는 그것이 완료되기까지 얼마나 가까웠는지 알아내는 방법인지 궁금합니다. 작업을 수행하는 데 백만 일이 걸릴 계획이라면 나는 그것을 죽일 것입니다.하지만 하루나 이틀만 더 필요하다면 실행하도록 하겠습니다.명령 쿼리는 다음과 같습니다.

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0
;

EXPLAIN은 여기서 문제가 아니며 업데이트하는 데 걸리는 시간을 어느 정도 정당화하기 위해 큰 테이블에 여러 인덱스가 있다는 점만 언급합니다.하지만 어쨌든 EXPLAIN은 다음과 같습니다.

Merge Join  (cost=127710692.21..135714045.43 rows=452882848 width=57)
  Merge Cond: (("outer".page_namespace = "inner".pl_namespace) AND ("outer"."?column4?" = "inner"."?column5?"))
  ->  Sort  (cost=3193335.39..3219544.38 rows=10483593 width=41)
        Sort Key: page.page_namespace, (page.page_title)::text
        ->  Seq Scan on page  (cost=0.00..439678.01 rows=10483593 width=41)
              Filter: (page_is_redirect = 0::numeric)
  ->  Sort  (cost=124517356.82..125285665.74 rows=307323566 width=46)
        Sort Key: pagelinks.pl_namespace, (pagelinks.pl_title)::text"
        ->  Seq Scan on pagelinks  (cost=0.00..6169460.66 rows=307323566 width=46)

이제 다음 중 하나를 삭제하기 위해 병렬 쿼리 명령도 보냈습니다. 페이지링크' 인덱스;물론 업데이트가 완료되기를 기다리고 있습니다(하지만 어쨌든 시도해 보고 싶었습니다!).그러므로 나는 아무것도 선택할 수 없습니다 페이지링크 데이터 손상을 두려워합니다(DROP INDEX 포스트마스터 프로세스를 종료하는 것이 안전하다고 생각하지 않는 한?).

따라서 데드 튜플의 양을 추적하는 테이블인지 궁금합니다. 업데이트가 작업을 완료하는 데 얼마나 빠르거나 얼마나 멀리 걸리는지 아는 것이 좋을 것입니다.

thx (postgresql은 내가 생각했던 것만 큼 지능적이지 않습니다.휴리스틱이 필요함)

도움이 되었습니까?

해결책

"PostgreSQL 문서를 읽었습니까?"설명 사용", 당신이 보여주는 출력을 해석하기 위해?

나는 일반 PostgreSQL 사용자가 아니지만 그 문서를 읽은 다음 EXPLAIN 당신이 보여주는 출력. 당신의 UPDATE 쿼리는 인덱스를 사용하지 않는 것 같습니다. page 그리고 pagelinks. 이 종류는 임시 디스크 파일이 필요할 정도로 의심 할 여지가 없습니다. temp_tablespace.

그런 다음 추정 데이터베이스 페이지가 읽는 것을 볼 수 있습니다. 그것의 최상위 EXPLAIN 출력이 말합니다 (cost=127710692.21..135714045.43). 여기의 장치는 디스크 I/O 액세스에 있습니다. 그래서이 작업을 수행하기 위해 1 억 3 천 5 백만 번 이상 디스크에 액세스 할 것입니다. UPDATE.

5ms를 찾는 시간이있는 10,000rpm 디스크조차도 최적의 조건에서 초당 200 I/O 작업을 최대한 활용할 수 있습니다. 이것은 당신의 의미입니다 UPDATE 해당 기간 동안 포화 디스크 I/O를 유지할 수 있더라도 188 시간 (7.8 일)의 디스크 I/O가 소요됩니다 (즉, 휴식없이 연속 읽기/쓰기). 이것은 불가능하며, 특히 실제 처리량이 적어도 몇 배나 꺼질 것으로 예상됩니다. 특히 그 동안이 서버를 다른 모든 작업에 사용하고 있었기 때문입니다. 그래서 나는 당신이 당신의 길의 일부일 뿐인 것 같아요 UPDATE.

그것이 나라면, 나는 첫날이 쿼리를 죽이고 또 다른 방법을 찾았을 것입니다. UPDATE 이로 인해 인덱스를 더 잘 활용했으며 디스크 정렬이 필요하지 않았습니다. 당신은 아마 단일 SQL 문으로 그것을 할 수 없을 것입니다.

당신의 DROP INDEX, 나는 그것이 단순히 막히고, 테이블에 대한 독점적 인 액세스를 기다리는 것을 기다리고 있다고 생각합니다. 그리고이 상태에있는 동안 아마 당신은 그것을 죽일 수 있다고 생각합니다.

다른 팁

이것은 매우 오래되었지만 업데이트를 모니터링할 수 있는 방법을 원한다면...시퀀스는 전역적으로 영향을 받으므로 다음을 수행하여 다른 세션에서 이 업데이트를 모니터링하기 위한 시퀀스를 만들 수 있습니다.

create sequence yourprogress; 

UPDATE pagelinks SET pl_to = page_id
    FROM page
    WHERE 
        (pl_namespace, pl_title) = (page_namespace, page_title)
        AND
        page_is_redirect = 0 AND NEXTVAL('yourprogress')!=0;

그런 다음 다른 세션에서 다음을 수행합니다(시퀀스는 전역적으로 영향을 받으므로 트랜잭션에 대해 걱정하지 마십시오).

select last_value from yourprogress;

그러면 영향을 받는 회선 수가 표시되므로 시간이 얼마나 걸릴지 추정할 수 있습니다.

마지막에 시퀀스를 다시 시작하여 또 다른 시도를 해보세요.

alter sequence yourprogress restart with 1;

아니면 그냥 버리세요:

drop sequence yourprogress;

인덱스가 필요하거나 Bill이 지적했듯이 모든 테이블에서 순차적 스캔을해야합니다.

CREATE INDEX page_ns_title_idx on page(page_namespace, page_title);
CREATE INDEX pl_ns_title_idx on pagelink(pl_namespace, pl_title);
CREATE INDEX page_redir_idx on page(page_is_redirect);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top