운영 체제로 디스크 공간을 반환하는 VACUUM


21

VACUUM일반적으로 특별한 경우를 제외하고 디스크 공간을 운영 체제로 반환하지 않습니다.
문서에서 :

표준 형식은 VACUUM테이블과 인덱스에서 데드 행 버전 을 제거하고 나중에 재사용 할 수있는 공간을 표시합니다. 그러나 테이블 끝에있는 하나 이상의 페이지가 완전히 사용 가능하고 독점 테이블 잠금을 쉽게 얻을 수있는 특수한 경우를 제외하고는 운영 체제로 공간을 리턴하지 않습니다. 반대로, VACUUM FULL데드 스페이스없이 완전한 새 버전의 테이블 파일을 작성하여 테이블을 적극적으로 압축합니다. 이렇게하면 테이블 크기가 최소화되지만 시간이 오래 걸릴 수 있습니다. 또한 작업이 완료 될 때까지 테이블의 새 사본을위한 추가 디스크 공간이 필요합니다.

문제는이 데이터베이스 one or more pages at the end of a table become entirely free가 달성 될 때 어떻게 상태를 나타낼 수 있는가입니다. 이를 통해 수행 할 수 VACUUM FULL는 있지만 구현 할 공간이 충분하지 않습니다. 다른 가능성이 있습니까?

답변:


29

공간을 OS로 되돌리려면을 사용하십시오 VACUUM FULL. 그것에있는 동안 나는 당신이 실행한다고 가정합니다 VACUUM FULL ANALYZE. 나는 매뉴얼을 인용한다 :

FULL

더 많은 공간을 회수 할 수있는 "전체"진공을 선택 하지만 훨씬 오래 걸리고 테이블을 독점적으로 잠급니다. 이 방법은 테이블의 새 복사본을 작성하고 작업이 완료 될 때까지 이전 복사본을 해제하지 않기 때문에 추가 디스크 공간이 필요합니다. 일반적으로 이는 테이블 내에서 많은 양의 공간을 확보해야하는 경우에만 사용해야합니다.

대담한 강조 광산.

CLUSTER 담보 효과로 달성합니다.

평범한 VACUUM목표는 일반적으로 목표를 달성하지 못합니다 ( "테이블 끝에 하나 이상의 페이지가 완전히 비어 있습니다" ). 기회가 발생할 때 행의 순서를 바꾸지 않고 파일의 실제 끝에서 빈 페이지 만 제거합니다 (수동 지침의 인용과 같이).

INSERT배치의 행과 DELETE다른 튜플이 추가되기 전에 행을 배치 할 때 실제 파일의 끝에 빈 페이지가 표시 될 수 있습니다 . 또는 충분한 행이 삭제되면 우연의 일치로 발생할 수 있습니다.

VACUUM FULL공간을 되 찾을 수없는 특수 설정도 있습니다 . 만나다:

테스트를 위해 테이블 ​​끝에 빈 페이지를 준비하십시오.

시스템 열 ctid은 행의 실제 위치를 나타냅니다. 해당 열을 이해해야합니다.

마지막 페이지에서 모든 행을 삭제하여 해당 작업을 수행하고 테이블을 준비 할 수 있습니다.

DELETE FROM tbl t
USING (
   SELECT (split_part(ctid::text, ',', 1) || ',0)')::tid     AS min_tid
        , (split_part(ctid::text, ',', 1) || ',65535)')::tid AS max_tid
   FROM   tbl
   ORDER  BY ctid DESC
   LIMIT  1
   ) d
WHERE t.ctid BETWEEN d.min_tid AND d.max_tid;

이제 마지막 페이지가 비어 있습니다. 동시 쓰기는 무시합니다. 해당 테이블에 대한 유일한 쓰기이거나 간섭을 피하기 위해 쓰기 잠금을 수행해야합니다.

쿼리는 적합한 행을 빠르게 식별하도록 최적화되어 있습니다. (A)의 두 번째 숫자 tid부호로 저장 튜플 인덱스 int265535유형 (최대이고 2^16 - 1그 상한 안전 그래서).

SQL Fiddle (다른 경우의 간단한 테이블 재사용)

행 / 테이블 크기를 측정하는 도구 :

디스크 꽉 참

이러한 작업을 수행하려면 디스크에 흔들기 공간이 필요합니다. / pg_repack대신 사용할 수 있는 커뮤니티 도구도 있습니다 . 독점 잠금을 피하지만 함께 사용할 수있는 여유 공간이 필요합니다. 매뉴얼 :VACUUM FULLCLUSTER

대상 테이블 및 인덱스보다 두 배 큰 여유 디스크 공간이 필요합니다.

최후의 수단으로 덤프 / 복원주기를 실행할 수 있습니다. 이는 테이블과 인덱스에서도 모든 부풀림을 제거합니다. 밀접하게 관련된 질문 :

저기에 대한 대답은 상당히 급진적입니다. 상황이 허용하는 경우 (외래 키 또는 행 삭제를 방해하는 다른 참조가없고) 테이블에 동시에 액세스 할 수없는 경우 다음을 수행 할 수 있습니다.

디스크 공간충분한 원격 컴퓨터 에서 테이블을 디스크로 덤프합니다 ( for ).-a--data-only

원격 쉘에서 덤프 테이블 데이터 :

pg_dump -h <host_name> -p <port> -t mytbl -a mydb > db_mytbl.sql

pg 세션 TRUNCATE에서 테이블은 다음과 같습니다.

-- drop all indexes and constraints here for best performance
TRUNCATE mytbl;

원격 쉘에서 동일한 테이블로 복원하십시오.

psql -h <host_name> -p <port> mydb -f db_mytbl.sql
-- recreate all indexes and constraints here

이제 죽은 행이나 부풀림이 없습니다.

그러나 아마도 더 간단하게 할 수 있습니까?

  • 관련없는 파일을 삭제 (이동)하여 디스크에 충분한 공간을 확보 할 수 있습니까?

  • 할 수 있습니다 VACUUM FULL, 첫째 작은 테이블, 하나 하나함으로써 충분한 디스크 공간을 확보?

  • bloated 인덱스에서 디스크 공간 을 실행 REINDEX TABLE하거나 REINDEX INDEX비울 수 있습니까?

무엇을하든 발진하지 마십시오 . 확실하지 않은 경우 먼저 안전한 장소에 모든 것을 백업하십시오.


어윈, 죄송합니다. 진공 청소기에 충분한 공간이 없다는 것을 잊었습니다. 질문을 업데이트했습니다.
모든 것에 대한 잘못된 것

@ Zapadlo : 업데이트 된 질문에 대한 장을 추가했습니다.
Erwin Brandstetter

포괄적 인 답변에 감사드립니다. 실제로 나는 가짜 업데이트에 의해 db 페이지의 끝에 죽은 행을 배치 할 수 있다고 생각 update table set field_1 = field_1했습니다.
모든 것에 대한 잘못된 것

@ Zapadlo : 내가 가진 아이디어는 이미 답에 있습니다. :) 나는 디스크에 상당한 흔들림 공간이 필요없이 죽은 튜플을 재정렬 할 수있는 도구를 모른다. (아무것도 없다는 것을 의미하지는 않습니다.)
Erwin Brandstetter

: 그들은 비록 아직 시도하지 않은,이 도구는 트릭을하지 말 code.google.com/p/pgtoolkit/source/browse/trunk/bin/...
잘못된 - 약 - 모든
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.