2013-11-04 3 views
7

내가 가진 다음 표 크기가이PostgreSQL의 : 몹시 느린 ORDER 키 순서로 기본 키 BY

enter image description here

같은 모델 : 지금

+------------------+-------------+ 
| Table   | Records | 
+------------------+-------------+ 
| JOB    |   8k | 
| DOCUMENT   |  150k | 
| TRANSLATION_UNIT |  14,5m | 
| TRANSLATION  |  18,3m | 
+------------------+-------------+ 

다음 쿼리

select translation.id 
from "TRANSLATION" translation 
    inner join "TRANSLATION_UNIT" unit 
    on translation.fk_id_translation_unit = unit.id 
    inner join "DOCUMENT" document 
    on unit.fk_id_document = document.id  
where document.fk_id_job = 11698 
order by translation.id asc 
limit 50 offset 0 

90 초 nds을 끝내십시오. ORDER BYLIMIT 절을 제거하면 19.5 초이 걸립니다. ANALYZE은 쿼리를 실행하기 직전에 모든 테이블에서 실행되었습니다.

이 특정 쿼리의 경우, 이러한 기준을 만족하는 레코드의 숫자 :

+------------------+-------------+ 
| Table   |  Records | 
+------------------+-------------+ 
| JOB    |   1 | 
| DOCUMENT   |  1200 | 
| TRANSLATION_UNIT | 210,000 | 
| TRANSLATION  | 210,000 | 
+------------------+-------------+ 

쿼리 계획 :

enter image description here

BY ORDER없이 수정에 대한 쿼리 계획 LIMIThere입니다.

데이터베이스 매개 변수 :

PostgreSQL 9.2 

shared_buffers = 2048MB 
effective_cache_size = 4096MB 
work_mem = 32MB 

Total memory: 32GB 
CPU: Intel Xeon X3470 @ 2.93 GHz, 8MB cache 

사람이 쿼리에 어떤 문제가 있는지 볼 수 있을까요?

UPDATE : BY ORDER없이 동일한 쿼리에 대한 Query plan (여전히 LIMIT 절).

+0

어떻게 Postgre에 대한 최적화 작업? 예를 들어 선택에서 선택할 수 있습니까? 그리고 옵티 마이저가 두 번 열리지 않고 주문할 수 있습니까? – Paul

+0

그냥 운 좋은 추측. 조인에서 where 절을 이동할 수 있습니까? 이 경우'where'를'and'로 바꿉니다. – foibs

+0

@foibs : 아무런 차이가 없습니다. Postgres 옵티마이 저는 두 버전이 동일하다는 것을 감지 할만큼 똑똑합니다. –

답변

1

번역 할 때 종합 색인이 있습니까 (fk_id_translation_unit, id)? 테이블을 통해 translation.id에 액세스 할 필요가 없으므로 도움이 될 것 같습니다.

+0

'fk_id_translation_unit'과'id' 컬럼을 결합한 복합 인덱스를 의미합니까? 나는하지 않지만 시도해 볼 수 있습니다. – twoflower

+0

필자가 보게되는 이점은 필요한 데이터를 검색하기 위해 변환 테이블 자체를 전혀 액세스 할 필요가 없다는 것입니다. –

+0

결과 집합에'TRANSLATION.id'가 필요하기 때문에 그렇습니다. PostgreSQL 성능 포럼의 한 남자는 데이터베이스를 비정규 화하고'fran_id_job '을'TRANSLATION'에 직접 추가하는 것을 추천했습니다. – twoflower

2

댓글이 너무 길었습니다. order by 절을 제거하면 사과와 오렌지를 비교합니다. order by이 없으면 쿼리의 처리 부분은 50 개의 행만 필요합니다.

order by을 사용하면 정렬하기 전에 모든 행을 생성해야하고 일부는 맨 위에 선택해야합니다. order bylimit 절을 제거하면 쿼리를 실행하는 데 얼마나 걸립니까?

translation.id이 기본 키인 사실은 처리에 여러 조인 (결과 필터링)이 필요하기 때문에 차이가 발생하지 않습니다.

편집 :

내가 먼저 테이블을 만들려면이는 CTE와 어떻게 작동하는지 궁금하고 또 다른 결과를 정렬하고 가져 :

with CTE as (
    select translation.id 
    from "TRANSLATION" translation 
      inner join "TRANSLATION_UNIT" unit 
      on translation.fk_id_translation_unit = unit.id 
      inner join "DOCUMENT" document 
      on unit.fk_id_document = document.id  
    where document.fk_id_job = 11698 
    ) 
select * 
from CTE 
order by translation.id asc 
limit 50 offset 0; 
+0

당신은 바로 Gordon입니다. 그 두 쿼리는 비교할 수 없습니다. 방금 ORDER BY와 LIMIT없이 쿼리를 실행했고 19.5 초가 걸렸습니다. 쿼리 계획은 [여기] (http://explain.depesz.com/s/Qs0) – twoflower

+0

@ twoflower입니다. . . 대량의 데이터가 있습니다. Postgres의 최적화 매개 변수에 익숙하지 않지만 더 많은 메모리를 사용하도록 버퍼 크기를 늘릴 수 있다면 성능이 향상 될 수 있습니다. –

+1

예, 볼륨이 꽤 큽니다. 그 이유는 레코드를 가져 오는 데 19.5 초가 걸린다는 사실에 놀라지 않습니다. 그러나 이상하게 여겨지는 것은이 데이터 세트 (cca 212,000 레코드)를 주문하면 70 초가 더 걸린다는 것입니다. – twoflower