SELECT는 VACUUM처럼 죽은 행을 제거합니까?


9

나는 테이블 VACUUM에서 SELECTing 행 VACUUM이 나중에 작업을 줄여야하는 것처럼 보이는 예기치 않은 동작을 발견 했습니다.

테스트 데이터

참고 : autovacuum은 비활성화되어 있습니다

CREATE TABLE numbers (num bigint);
ALTER TABLE numbers SET (
  autovacuum_enabled = 'f',
  toast.autovacuum_enabled = 'f'
);

INSERT INTO numbers SELECT generate_series(1, 5000);

시험 1

이제 모든 행에서 업데이트를 실행합니다.

UPDATE numbers SET num = 0;

그리고 우리는 실행할 때 VACUUM (VERBOSE) numbers;우리가 얻을,

INFO:  vacuuming "public.numbers"
INFO:  "numbers": removed 5000 row versions in 23 pages
INFO:  "numbers": found 5000 removable, 5000 nonremovable row versions in 45 out of 45 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 6585
There were 0 unused item pointers.

시험판 2

이제 우리는 다른 것을 발행 UPDATE하지만 이번에는 SELECT나중에 추가합니다 .

UPDATE numbers SET num = 1;
SELECT * FROM numbers;

그리고 우리는 실행할 때 VACUUM (VERBOSE) numbers;우리가 얻을,

INFO:  vacuuming "public.numbers"
INFO:  "numbers": removed 56 row versions in 22 pages
INFO:  "numbers": found 56 removable, 5000 nonremovable row versions in 45 out of 45 pages
DETAIL:  0 dead row versions cannot be removed yet, oldest xmin: 6586
There were 56 unused item pointers.

여기서 정확히 무슨 일이 일어나고 있습니까? SELECT방문한 페이지에서 죽은 튜플을 제거한 후에 두 번째 버전을 실행하는 이유는 무엇 VACUUM입니까?

macOS 10.14.5에서 Postgres 11.3을 실행하고 있습니다.


2
어떤 클라이언트를 사용하여 명령을 실행합니까? 자동 커밋이 활성화되어 있습니까?
mustaccio 2016 년

2
"VACUUM 테이블은 기본적으로 SELECT * FROM table from hood입니까?"라는 질문을 삭제하겠습니다. 나는 그것이 좋은 후속 조치라고 생각합니다. 여기서 대답은 단순히 SELECT가 죽은 행을 제거 할 수 있으며 VACUUM과 공통으로 공유한다는 것입니다. 그것들의 차이점은 XID 롤오버와 다른 많은 것들에 대해 매우 철저한 대화가 될 것입니다. 그 질문은 기본적으로 "죽은 줄을 제거하는 것 외에 진공이하는 다른 일"입니다. (어떤 종류의 모호한 것입니까?)
Evan Carroll

@mustaccio 나는 ActiveRecord를 사용하는 Ruby 스크립트로 이러한 테스트를 수행했습니다. ActiveRecord는 PG gem을 사용합니다. BEGIN이 명시 적으로 사용되지 않으면 COMMIT를 발행 할 필요가 없으므로 자동 커밋이 기본적으로 활성화되어 있다고 생각합니다.
rafbm

답변:


5

/ r / PostgreSQL의이 게시물 부터 Laurenz Albe답변에 이르기까지 힙 전용 튜플 (HOT) 업데이트가 책임이있는 것 같습니다. HOT 업데이트 설명 에서src/backend/access/heap/README.HOT

효과적으로, 페이지가 거의 가득 차고 (<10 % 사용 가능) 버퍼 정리 잠금을 확보 할 수있을 때 튜플 검색 중에 공간 회수가 발생합니다. 이 수단 UPDATE, DELETESELECTCAN 트리거 공간 간척하지만, 종종 동안 INSERT ... VALUES이 행을 검색하지 않기 때문에.

따옴표는 원래 답변에 없지만 나머지는 따옴표입니다.

이 이론을지지하거나 반박하려면 다음 쿼리를 실행하십시오.

SELECT n_tup_upd, n_tup_hot_upd
FROM pg_stat_user_tables
WHERE schemaname = 'public' AND relname = 'TABLE_NAME';

경우 n_tup_hot_upd0보다 큰 경우, 우리는 사건을 가지고있다.


지금 우리는 이야기하고 있습니다. +1
mustaccio 2012

HOT가 좋은 설명 인 것 같습니다. I CREATE INDEX idx_numbers ON numbers USING btree (num)인 경우 VACUUM 출력이로 변경됩니다 INFO: "numbers": removed 5000 row versions in 45 pages. 그러나 인덱스없는 시나리오에서는 n_tup_hot_updUPDATE와 SELECT 사이와 SELECT와 VACUUM 사이에서 항상 0입니다. 또한 SELECT pg_sleep(10)통계가 최신 상태가되도록 각 문 사이 에서 실행해야했습니다 ( seq_scan: 2UPDATE 및 SELECT 중 하나 참조 ).
rafbm 2016

이 경우 Select가 WAL을 생성합니까? 나는 선택이 WAL을 전혀 생성하지 않는다는 인상을 받았다. 그렇다면, 이는 죽은 행 제거가 모든 슬레이브에 전파됨을 의미합니다. 그렇지 않은 경우, 이는 슬레이브에서 진공 청소기가 여전히 필요함을 의미합니다. 또한 마스터와 슬레이브가 조금 동일하지 않다는 것을 의미합니다. 흠, 아마도 조사를해야하고 질문이나 대답을 게시해야 할 수도 있습니다.
Colin 't Hart

1

인덱싱되지 않은 테이블의 특수한 경우 예, SELECT는 VACUUM과 동일한 작업을 수행 할 수 있습니다 (사후 행 제거에 관한 한).


3
설명을 추가해 주시겠습니까?
Laurenz Albe 2016 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.