프로그래밍 방식으로 포스트 레코드 데이터베이스에 천만 개의 레코드를 삽입해야합니다. 현재 하나의 “쿼리”에 1000의 insert 문을 실행하고 있습니다.
이 작업을 수행하는 더 좋은 방법이 있습니까, 내가 모르는 대량 삽입 문이 있습니까?
답변
PostgreSQL에는 처음에 데이터베이스를 가장 잘 채우는 방법에 대한 가이드 가 있으며 대량로드 행에 COPY 명령을 사용하는 것이 좋습니다 . 이 가이드에는 데이터를로드하기 전에 인덱스와 외래 키를 제거하고 나중에 다시 추가하는 등 프로세스 속도를 높이는 방법에 대한 유용한 팁이 있습니다.
답변
COPY를 사용하는 대신 Postgres가 지원하는 다중 행 값 구문이 있습니다. 로부터 문서 :
INSERT INTO films (code, title, did, date_prod, kind) VALUES
('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');
위의 코드는 두 개의 행을 삽입하지만 준비된 명령문 토큰의 최대 수에 도달 할 때까지 임의로 확장 할 수 있습니다 (999 달러 일 수도 있지만 100 % 확신 할 수는 없습니다). 때로는 COPY를 사용할 수 없으며 이러한 상황을 대체 할 가치가 있습니다.
답변
작업 속도를 높이는 한 가지 방법은 트랜잭션 내에서 여러 삽입 또는 복사를 명시 적으로 수행하는 것입니다 (예 : 1000). Postgres의 기본 동작은 각 명령문 이후에 커밋하는 것이므로 커밋을 일괄 처리하여 약간의 오버 헤드를 피할 수 있습니다. Daniel의 답변 안내서에 나와 있듯이 자동 커밋을 비활성화해야 작동 할 수 있습니다. 또한 wal_buffers의 크기를 16MB로 늘릴 것을 제안하는 주석도 도움이 될 수 있습니다.
답변
UNNEST
배열이있는 함수는 다중 행 VALUES 구문과 함께 사용할 수 있습니다. 나는이 방법을 사용하는 것보다 느린이라고 생각 해요 COPY
하지만 psycopg와 파이썬과 일에 나에게 유용하다 (파이썬 list
에 전달 된 cursor.execute
페이지가됩니다 ARRAY
) :
INSERT INTO tablename (fieldname1, fieldname2, fieldname3)
VALUES (
UNNEST(ARRAY[1, 2, 3]),
UNNEST(ARRAY[100, 200, 300]),
UNNEST(ARRAY['a', 'b', 'c'])
);
VALUES
추가 존재 확인과 함께 부속 선택을 사용 하지 않고 :
INSERT INTO tablename (fieldname1, fieldname2, fieldname3)
SELECT * FROM (
SELECT UNNEST(ARRAY[1, 2, 3]),
UNNEST(ARRAY[100, 200, 300]),
UNNEST(ARRAY['a', 'b', 'c'])
) AS temptable
WHERE NOT EXISTS (
SELECT 1 FROM tablename tt
WHERE tt.fieldname1=temptable.fieldname1
);
대량 업데이트와 동일한 구문 :
UPDATE tablename
SET fieldname1=temptable.data
FROM (
SELECT UNNEST(ARRAY[1,2]) AS id,
UNNEST(ARRAY['a', 'b']) AS data
) AS temptable
WHERE tablename.id=temptable.id;
답변
COPY table TO ... WITH BINARY
” 텍스트 및 CSV 형식보다 다소 빠른 “것을 사용할 수 있습니다 . 삽입 할 행이 수백만 개이고 이진 데이터에 익숙한 경우에만이 작업을 수행하십시오.
다음은 바이너리 입력과 함께 psycopg2를 사용하는 Python 의 예제 레시피입니다 .
답변
주로 데이터베이스의 (기타) 활동에 따라 다릅니다. 이와 같은 작업은 다른 세션을 위해 전체 데이터베이스를 효과적으로 고정시킵니다. 다른 고려 사항은 데이터 모델과 제약 조건, 트리거 등의 존재입니다.
첫 번째 방법은 항상 : 목표 테이블과 비슷한 구조로 (임시) 테이블을 만들고 (테이블 = tmp AS select * from target where 1 = 0) 파일을 임시 테이블로 읽는 것부터 시작하십시오. 그런 다음 확인할 수있는 항목을 확인합니다. 중복, 대상에 이미 존재하는 키 등
그런 다음 “대상 선택 * tmp에서 삽입”또는 이와 유사한 작업을 수행합니다.
이것이 실패하거나 너무 오래 걸리면 중단하고 다른 방법을 고려하십시오 (일시적으로 색인 / 제약 조건 삭제 등).
답변
네이티브 libpq 메소드를 사용하여 매우 빠른 Postgresq 데이터 로더를 구현했습니다. 내 패키지를보십시오 https://www.nuget.org/packages/NpgsqlBulkCopy/
