테이블에 널 입력 가능 컬럼 추가에 10 분 이상 소요


11

테이블에 새 열을 추가하는 데 문제가 있습니다.
두 번 실행하려고했지만 10 분 이상 실행 한 후 잠금 시간으로 인해 쿼리를 취소하기로 결정했습니다.

ALTER TABLE mytable ADD mycolumn VARCHAR(50);

유용한 정보:

  • PostgreSQL 버전 : 9.1
  • 행 수 : ~ 250K
  • 열의 수 : 38
  • 널 입력 가능 컬럼 수 : 32
  • 제약의 개수 : 5 (1 PK, 3 FK, 1 UNIQUE)
  • 인덱스 수 : 1
  • 운영체제 유형 : Debian Squeeze 64

PostgreSQL이 nullable 열을 관리하는 방법에 대한 흥미로운 정보 를 찾았습니다 (HeapTupleHeader를 통해).

내 첫 번째 추측은이 테이블에 이미 8 비트의 널 입력 가능 열이 32 개 있기 때문에 MAXALIGNHeapTupleHeader는 4 바이트 길이입니다 (확인되지 ​​않았으며 그렇게하는 방법을 모르겠습니다).

따라서 새로운 Null 허용 열을 추가하려면 모든 행에서 HeapTupleHeader를 업데이트해야 새로운 8 비트가 추가되어 MAXALIGN성능 문제가 발생할 수 있습니다.

그래서 nullable 열 중 하나를 변경하여 nullable 열의 수를 31로 줄이려고 내 추측이 참인지 확인했습니다.

ALTER TABLE mytable ALTER myothercolumn SET NOT NULL;

불행히도이 변경은 5 분 이상 걸리는 시간이 오래 걸리므로 중단했습니다.

이 성능 비용의 원인이 무엇인지 알고 있습니까?


1
글쎄, 나는 그것의 일부를 말할 수있다 : 바이너리 유형과 호환되지 않는 다른 유형으로 열 유형을 변경하면 실제로 새로운 열을 생성하고 데이터를 복사하며 이전 열을 삭제 된 것으로 설정합니다. 그러나 SET NOT NULL유형을 변경하지 않고 제약 조건을 추가하기 만하지만 제약 조건을 테이블과 비교하여 확인 해야하며 전체 테이블 스캔이 필요합니다. 9.4는 약한 자물쇠를 사용하여 이러한 경우 중 일부를 개선하지만 여전히 꽤 무겁습니다.
Craig Ringer

1
느리게 수행되고 있다고 의심되기 전에 ALTER TABLE이 잠금을 기다리는 것이 아닌지 확인해야합니다. 확인한 경우 질문에 언급하십시오.
Daniel Vérité

Craig와 Daniel에게 감사합니다. alter 명령을 실행하면 pg_stat_activity에 "true"대기 중으로 표시됩니다. 잠금을 기다리는 것을 의미한다고 가정합니다. 확인하기에 좋은 방법입니까? 그건 그렇고,이 변경을 실행하기 전에 모든 것이 잘 진행되지만 시작 후 몇 초가 지나면 잠금 수가 증가합니다.

더 잘 보려면 wiki.postgresql.org/wiki/Lock_dependency_information 에서 쿼리를 시도하십시오 . 커밋을 잊는 트랜잭션이 남아 있거나이 테이블을 사용하여 항상 바쁘게 유지하는 활동이 많습니다.
Daniel Vérité

dba.SE에 더 적합 할 수 있습니다.
Erwin Brandstetter

답변:


8

여기에 몇 가지 오해가 있습니다.

널 비트 맵 입니다 하지 힙 튜플 헤더의 일부입니다. 문서 당 :

고정 크기 헤더 (대부분의 컴퓨터에서 23 바이트를 차지함)와 선택적 null 비트 맵이 있습니다 ...

32 개의 널 입력 가능 열은 다음 두 가지 이유로 의심되지 않습니다.

  • 널 비트 맵은 행당 추가 되며 행에 실제 NULL하나 이상있는 경우에만 추가 됩니다 . 널 입력 가능 컬럼은 직접적인 영향을 미치지 않으며 실제 NULL값만 영향을 줍니다. 널 비트 맵이 할당되면 항상 완전히 할당됩니다 (모두 또는 아무것도 아님). 널 비트 맵의 ​​실제 크기는 열당 1 비트 이며 다음 바이트로 올림됩니다 . 현재 소스 코드 당 :

    #define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8)
  • 널 비트 맵은 힙 튜플 헤더 뒤에 할당되고 선택적 OID와 행 데이터가 뒤 따릅니다. OID 또는 행 데이터의 시작은 t_hoff헤더에 표시됩니다 . 주석 당 소스 코드 :

    t_hoff는 MAXALIGN의 배수 여야합니다.

  • 힙 튜플 헤더 뒤에는 23 바이트를 차지하는 사용 가능한 바이트가 하나 있습니다. 따라서 최대 8 열의 행에 대한 널 비트 맵은 추가 비용없이 효과적으로 제공됩니다. 표 9 번째 열이, t_hoff다른 전진 MAXALIGN(보통 8) 다른 열 (64)을 제공하기 위해 바이트. 따라서 다음 경계는 72 열입니다.

MAXALIGN데비안 머신에서 Postgres 9.3의 일반적인 설치 예를 포함하여 PostgreSQL 데이터베이스 클러스터 (포함 ) 의 제어 정보를 표시하려면 :

    sudo /usr/lib/postgresql/9.3/bin/pg_controldata /var/lib/postgresql/9.3/main

인용 한 관련 답변의 지침을 업데이트했습니다 .

모든 것을 제외하고, ALTER TABLE명령문이 전체 테이블 다시 쓰기를 트리거 하더라도 (데이터 유형 변경) 250K는 실제로 그다지 크지 않으며 중간 정도의 기계에서 몇 초가됩니다 (행이 비정상적으로 크지 않은 경우) . 10 분 이상이 완전히 다른 문제를 나타냅니다. 당신의 진술은 아마도 테이블을 잠그려고 기다리고 있습니다.

증가하는 항목 수는 pg_stat_activity더 많은 공개 트랜잭션 을 의미합니다. 작업이 완료되기를 기다려야하는 테이블에 대한 동시 액세스 (대부분 가능성이 있음)를 나타냅니다.

어둠 속에서 몇 발

가능한 테이블 팽창을 확인하고, 온화 VACUUM mytable하거나 더 공격적인 시도 VACUUM FULL mytable– 동일한 동시성 문제가 발생할 수 있습니다.이 양식은 독점 잠금을 획득하기 때문입니다. 대신 pg_repack 을 사용해보십시오 ...

인덱스, 트리거, 외래 키 또는 기타 제약 조건, 특히 열과 관련된 문제와 관련하여 가능한 문제를 검사하는 것으로 시작합니다. 특히 손상된 인덱스가 관련되어 있습니까? 시도 REINDEX TABLE mytable;또는 DROP그들과의 모든 후에 다시는-추가 ALTER TABLE 동일한 트랜잭션에서 .

밤이나 부하가 많지 않을 때마다 명령을 실행하십시오.

무차별 대입 방법은 서버에 대한 액세스를 중지 한 후 다시 시도하는 것입니다.

그것을 고정시킬 수 없다면, 현재 버전이나 다가오는 9.4로 업그레이드하는 것이 도움 이 될 수 있습니다. 큰 테이블 및 잠금 세부 사항에 대한 몇 가지 개선 사항이 있습니다. 그러나 DB에 손상된 것이 있으면 먼저 알아 내야합니다.


2
거의 확실하게 잠겨 있습니다. 그러나 테스트로서 항상 테이블의 사본을 작성하고이를 변경할 수 있습니다. 시간이 오래 걸리지 않으면 실제 수정이 아니라는 것을 알 수 있습니다.

설명 해주셔서 감사합니다. 나는 당신이 옳다고 생각합니다. 그것은 잠금 문제인 것 같습니다. pg_stat_activity를 확인하면 ALTER에 "대기"사실이 있음을 알 수 있습니다. 내가 알 수없는 것은 ALTER가 테이블에서 잠금을 얻을 수없는 이유입니다. 실행중인 쿼리를 찾을 수 없어도 얻을 수없는 것처럼 보입니다. 그러나 ALTER가 실행되기 시작하면 다른 모든 쿼리가 완료되기를 기다리고 있습니다. 따라서 활동은 ALTER가 다른 모든 쿼리를 잠그지 만 ALTER가 잠금을 얻지 못했음을 나타냅니다. 잘 모르는 것이 있다고 생각합니다!?

@MatthieuVerrecchia : Richard가 제안한 테스트를 시도 했습니까?
Erwin Brandstetter

1
방금 내 테이블을 새로운 테이블로 복제했습니다 (pg_dump-> pg_sql 사용). 새 열이 50ms 내에 올바르게 추가되어 잠금 문제를 확인합니다. 그런데 ALTER가 실제로 표준 DB 활동으로 잠글 수없는 이유를 여전히 이해하지 못합니다.

1
@ ErwinBrandstetter 나는 당신의 제안을 따르고 VACUUM을 시도한 다음 REINDEX를 시도했습니다. REINDEX도 차단되어 잠금을 획득 할 수 없었습니다. 조사를 마친 후에도 문제가 더 간단했습니다. 거래가 열린 상태에서 <IDLE>이 ​​1 주 남았습니다. 문제가 해결되었습니다. 모든 정보는 매우 유용했습니다.
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.