2009-09-24 4 views
2

며칠 전, 나는 꽤 표준 장고 설정과 예기치 않은 성능 문제로 달렸다. 다가올 기능을 위해 매시간 테이블을 재생성해야하는데, 디스크의 약 100,000 행, 디스크의 9M, pgAdmin에 따른 10M 색인이 포함됩니다.는 PostgreSQL을, 외래 키 삽입 속도 및 장고

문제는별로 삽입한다는 것입니다 말 그대로 100 % 디스크 바쁜 시간 3 분까지 나이, 무슨 일이든하는 방법. 그것은 프로덕션 사이트에서 원하는 것이 아닙니다. 삽입이 트랜잭션에 있거나, 일반 삽입, 다중 행 삽입, COPY FROM 또는 심지어 INSERT INTO t1 SELECT * FROM t2를 통해 발행되었는지는 중요하지 않습니다. 이 장고의 잘못이 아닙니다 알아 차리지 후

, 나는 시행 착오 경로를 따라, 그리고 야, 문제는 모든 외부 키를 삭제 한 후 사라졌다! 3 분 대신에 INSERT INTO SELECT FROM은 실행하는데 1 초도 채 걸리지 않았습니다. 디스크의 테이블 < = 20M에 대해서는 그리 놀라운 일이 아닙니다. 입니다. PostgreSQL은 3 개의 외래 키를 사용하여 삽입을 180x 느리게 처리합니다.

오, 디스크 활동은 모든 것이 RAM에 캐시되므로 순수한 쓰기였습니다. 쓰기 만 디스크로 이동합니다. 3MB/sec * 180은이 새로운 테이블이 디스크에서 차지하는 20MB보다 많은 데이터이므로 PostgreSQL은 참조 된 테이블의 모든 행을 다루기 위해 매우 열심히 노력하고있는 것처럼 보입니다. 180 년대에는 WAL이 없었고, 장고에서는 직접 psql을 테스트하고 WAL 로깅을 위해 ~ 50 %의 오버 헤드를 추가했습니다. @commit_on_success, 같은 속도 느려, 나는 심지어 psycopg2와 함께 다중 행 삽입 및 COPY FROM 구현했습니다. 이것은 또 다른 이상한 일입니다. 어떻게 10M 값의 인서트가> 10x 16M 로그 세그먼트를 생성 할 수 있습니까?

표 레이아웃 : 시리얼 번호 차, INT32 무리 3 외래 키

  • 작은 테이블, 198 행, 디스크 16K
  • 큰 테이블 1.2M 행 데이터 (59) + (89)에 인덱스

    디스크에 MB
  • 큰 테이블, 2.2M 행, 198 그래서 + 210메가바이트

, 나는 운명하고 수동 외부 키를 떨어 뜨리거나 bla_id X3를 저장 정의하여 매우 취소 장고 방식으로 테이블을 사용 모델을 사용하여 건너 뜁니다. nKey? 이 문제를 해결하기위한 마법의 해독제/Pg 설정에 대해 듣고 싶습니다.

답변

0

정상적인 동작입니다. 데이터베이스에 대량 삽입 할 때 테이블에 인덱스, 외래 키 또는 트리거가 있으면 행별로 검사해야합니다. 따라서 일반적으로 삭제, 삽입 (가능한 경우 사본 사용)을 수행 한 다음 색인, FK 및 트리거를 다시 작성하려고합니다. 워드 프로세서에

이 페이지를 조정할 수 있습니다 더 자동 커밋, maintenance_work_mem로에 대한 자세한 내용 및 checkpoint_segments 있습니다 http://www.postgresql.org/docs/8.4/interactive/populate.html

+0

이미 확인했습니다. 문제는 검사가 아니라 두 인덱스에서 O (n log (n)) 인덱스를 찾아 메모리에서 읽는 것입니다. 아니요, 문제는 디스크에 발생한 많은 양의 쓰기입니다. 지수를 떨어 뜨리면 성능이 크게 향상되지 않으며 자동 커밋 - 원본 게시물에 명시된 것과 동일한 결과를 얻었거나없이 결과를 시도했습니다. –

+0

FK를 삭제하는 것이 대량 삽입물의 성능을 향상시키지 않는 데이터베이스를 아직 보지 못했습니다. 그들을 떨어 뜨리고 재창조하는 것이 현명해야합니다. 그것은 분명히 좋은 생각입니다. – hgmnz

0

어쩌면 당신은 당신의 테이블에 트리거가를, 당신은 알고 또는 기억이없는 모든 행에 화재 삽입/삭제됨. "psql"을 사용하여 데이터베이스에 연결할 수 있습니까? 그렇다면 모든 테이블에 대해 "\ d + table_name"의 출력을 분석하십시오.

데이터베이스를 덤프하거나 가져 오기를 수행하고 데이터베이스를 다시 덤프 할 수도 있습니다. 덤프를 비교하여 다른 테이블 내용이 변경되었는지 확인하십시오. 이 IO 읽기를 기다릴 필요가없는 경우

+0

psql/pgAdmin은 일반 테이블, 3 FK, 1 PK, 3 인덱스와 거의 동일한 것을 보여줍니다. FK의 삽입 성능 만 떨어지게됩니다. Django가 FK를 사용하여 일관성을 유지하도록 권장하므로 FK가 모든 곳에서 사용되고 있지만 포스트 그레스는 제대로 처리하지 못합니다. Postgres 개발자들에게도 질문 할 것입니다. –

2

100.000 FK 검사에 대한 2~5초을해야합니다. 테이블에 삽입하는 것보다 훨씬 느리지 만 얻은 시간보다 훨씬 빠릅니다.모든 외래 키 색인 것을

확인 :

는 (? 나는 참조 된 컬럼에 인덱스가 아닌 참조 컬럼에 대해서 이야기하고 그것을 가지고)

하면 products.category_id 참조 카테고리 (id), 그리고 category.id에 대한 색인이 없기 때문에, FK를 점검 할 필요가있을 때마다 테이블을 검사해야합니다.

어떤 것이 아닌지 알아 보려면 1 FK, 2 FK로 삽입하십시오. 어느 것이 책임인지 알 수 있습니다.

예, 테이블을 자르면 모든 제약 조건과 인덱스를 삭제하고 대량 삽입 후에 다시 작성하는 것이 빠릅니다.

+0

다른 테이블의 기본 ID 만 참조합니다. 그렇기 때문에 인덱싱됩니다. 아니, 그것은 읽기 io : 신뢰성 및 성능 모니터에서, 나는 전혀 디스크에서 읽는 것을 볼 수 있습니다. 쓰기 : 설명 할 수없는 많은. 잘라 내기 - 나는 항상 그렇게 할 것이라고 생각했지만, 삭제 된 삽입주기로 전환하여 많은 행을 그대로 유지했습니다. 어떻게 든 9MB의 데이터 테이블을 만드는 것이 예상보다 오래 걸립니다. –

+0

당신의 기대가 부당하다고 생각합니다. 이 답변에는 필요한 모든 것이 있습니다. 추적해야하는 패턴은 잘라내 기, 모든 제약 조건 및 색인 삭제, 데이터로드, 제약 조건 및 색인 교체입니다. 이것은 django를 사용해서는 안되는 것처럼 들린다. ETL 도구는 사용자가 따라 다니는 패턴에 더 가까운 소리로 들리기 때문에 살펴보십시오. – Andrew

0

EXPLAIN ANALYZE INSERT INTO bleh ...가 모든 삽입 트리거의 타이밍을 표시한다는 것을 잊어 버렸습니다.

+0

FK가 아니거나 다른 버전에 대해 이야기하고 있습니까? 결과 (비용 = 0.00..0.02 행 = 1 너비 = 0) (실제 시간 = 0.007..0.009 행 = 1 루프 = 1) 간단한 1 행 삽입에 대한 총 실행 시간 : 32.171 ms. –