[postgresql] PostgreSQL-varchar 열의 크기를 더 작은 길이로 변경하십시오.

ALTER TABLE정말 큰 테이블 (약 3 천만 행) 의 명령에 대한 질문이 있습니다 . 해당 열 중 하나 varchar(255)varchar(40)입니다. 로 크기를 조정하고 싶습니다 . 기본적으로 다음 명령을 실행하여 열을 변경하고 싶습니다.

ALTER TABLE mytable ALTER COLUMN mycolumn TYPE varchar(40);

프로세스가 매우 길더라도 문제가 없지만 ALTER TABLE 명령 동안 내 테이블을 더 이상 읽을 수없는 것 같습니다. 더 똑똑한 방법이 있습니까? 어쩌면 새 열을 추가하고 이전 열의 값을 복사하고 이전 열을 삭제하고 마지막으로 새 열의 이름을 바꾸겠습니까?

어떤 단서라도 대단히 감사하겠습니다! 미리 감사드립니다.

참고 : PostgreSQL 9.0을 사용합니다.



답변

데이터를 변경하지 않고 PostgreSQL 테이블의 열 크기 조정 에서이를 수행하는 방법에 대한 설명이 있습니다 . 데이터베이스 카탈로그 데이터를 해킹해야합니다. 이 작업을 공식적으로 수행하는 유일한 방법은 ALTER TABLE을 사용하는 것입니다. 앞에서 언급했듯이 변경이 실행되는 동안 전체 테이블이 잠기고 다시 작성됩니다.

이를 변경하기 전에 문서 의 문자 유형 섹션 을 읽으십시오 . 여기서 알아야 할 모든 종류의 이상한 경우. 길이 점검은 값이 행에 저장 될 때 수행됩니다. 거기에서 하한을 해킹하면 기존 값의 크기가 전혀 줄어들지 않습니다. 변경 후 필드 길이가 40자를 초과하는 행을 찾아 전체 테이블을 스캔하는 것이 좋습니다. 누군가 수동으로 자르는 방법을 알아야합니다. 따라서 누군가가 그 행의 내용을 업데이트하려고하면 시점에서 너무 크게 거부하기 때문에 너무 큰 잠금에서만 다시 잠금을 설정해야합니다. 행의 새 버전을 저장합니다. 사용자에게 즐거움이 뒤 따릅니다.

VARCHAR은 PostgreSQL에 존재하는 끔찍한 유형으로, SQL 표준의 관련 끔찍한 부분 만 준수합니다. 다중 데이터베이스 호환성에 신경 쓰지 않는다면 데이터를 TEXT로 저장하고 길이를 제한하는 제약 조건을 추가하십시오. 이 테이블 잠금 / 재 작성 문제없이 변경할 수 있으며, 약한 길이 검사보다 무결성 검사를 더 많이 수행 할 수 있습니다.


답변

PostgreSQL 9.1에는 더 쉬운 방법이 있습니다

http://www.postgresql.org/message-id/162867790801110710g3c686010qcdd852e721e7a559@mail.gmail.com

CREATE TABLE foog(a varchar(10));

ALTER TABLE foog ALTER COLUMN a TYPE varchar(30);

postgres=# \d foog

 Table "public.foog"
 Column |         Type          | Modifiers
--------+-----------------------+-----------
 a      | character varying(30) |


답변

좋아, 아마 파티에 늦었을 수도 있지만 …

귀하의 경우에 열의 크기를 조정할 필요가 없습니다!

Postgres는 다른 데이터베이스와 달리 문자열을 수용하기에 충분한 공간 만 사용하기에 충분합니다 (더 긴 문자열의 경우 압축을 사용하더라도). 열이 VARCHAR (255)로 선언 된 경우에도 40 자 문자열을 열의 공간 사용량은 40 바이트 + 1 바이트의 오버 헤드입니다.

짧은 문자열 (최대 126 바이트)에 대한 스토리지 요구 사항은 1 바이트 + 실제 문자열이며 문자의 경우 공백을 포함합니다. 긴 문자열은 1 대신 4 바이트의 오버 헤드를 갖습니다. 긴 문자열은 시스템에 의해 자동으로 압축되므로 디스크의 물리적 요구 사항은 더 적을 수 있습니다. 매우 긴 값은 백그라운드 테이블에 저장되므로 더 짧은 열 값에 빠르게 액세스하는 데 방해가되지 않습니다.

( http://www.postgresql.org/docs/9.0/interactive/datatype-character.html )

VARCHAR의 크기 사양은 삽입 된 값의 크기를 확인하는 데만 사용되며 디스크 레이아웃에는 영향을 미치지 않습니다. 실제로 VARCHAR 및 TEXT 필드는 Postgres에 동일한 방식으로 저장됩니다 .


답변

VARCHAR을 32에서 8로 자르려고 시도하고 동일한 문제에 직면했습니다. ERROR: value too long for type character varying(8) . 고객의 선택에 따라 다른 DBMS로 전환해야하는 자체 제작 JPA와 유사한 구조를 사용하고 있기 때문에 가능한 한 SQL에 가깝게 유지하고 싶습니다 (PostgreSQL이 기본 구성). 따라서 시스템 테이블을 변경하는 트릭을 사용하고 싶지 않습니다.

나는 : 의 USING진술을 사용하여 끝내었다 ALTER TABLE.

ALTER TABLE "MY_TABLE" ALTER COLUMN "MyColumn" TYPE varchar(8)
USING substr("MyColumn", 1, 8)

@raylu가 지적했듯이 ALTER테이블에 대한 독점 잠금을 획득하므로 다른 모든 작업은 완료 될 때까지 지연됩니다.


답변

redshift postgresql에서 새 열을 추가하고 이전 열을 새 것으로 교체하면 자세한 내용은이 링크를 참조하십시오 https://gist.github.com/mmasashi/7107430

BEGIN;
LOCK users;
ALTER TABLE users ADD COLUMN name_new varchar(512) DEFAULT NULL;
UPDATE users SET name_new = name;
ALTER TABLE users DROP name;
ALTER TABLE users RENAME name_new TO name;
END;


답변

다음 은 Greg Smith가 설명하는 페이지 의 캐시 입니다. 또한 죽는 경우, alter 문은 다음과 같습니다 :

UPDATE pg_attribute SET atttypmod = 35+4
WHERE attrelid = 'TABLE1'::regclass
AND attname = 'COL1';

테이블이 TABLE1 인 경우 열은 COL1이며이를 35 자로 설정하려고합니다 (링크에 따라 레거시 목적에 +4가 필요하며, 주석에서 AH가 참조하는 오버 헤드 일 수 있음).


답변

변경 사항을 트랜잭션에 넣은 경우 테이블을 잠그면 안됩니다.

BEGIN;
  ALTER TABLE "public"."mytable" ALTER COLUMN "mycolumn" TYPE varchar(40);
COMMIT;

이것은 400k 개 이상의 행이있는 테이블에서 몇 초 만에 빠르게 타오르는 데 효과적이었습니다.