2012-04-13 2 views
1

불행히도 프로덕션 (90 개 열이있는 테이블의 3 milion 레코드)에서 약 2 분 만에 두 개의 조건으로 선택/결합하는 쿼리를 실행하는 큰 PostgreSQL 프로젝트에서 작업하고 있습니다.postgresql optimization

내 쿼리에 최적화 할 사항이 없다고 가정하면 더 빠르게 실행되도록 수정할 수있는 설정이 있습니까? 이 데이터베이스의 구성입니다, 나는 내 요구에 맞는 것을 아무 생각이 없다 :

version PostgreSQL 8.4.4 on i686-pc-linux-gnu, compiled by GCC gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-44), 32-bit 
checkpoint_completion_target 0.9 
checkpoint_segments 10 
custom_variable_classes pg_stat_statements 
effective_cache_size 1GB 
lc_collate fr_FR.UTF-8 
lc_ctype fr_FR.UTF-8 
listen_addresses * 
log_autovacuum_min_duration 0 
log_line_prefix %t [%p]: [%l-1] user=%u,db=%d 
log_min_duration_statement 30s 
logging_collector on 
maintenance_work_mem 128MB 
max_connections 100 
max_stack_depth 2MB 
pg_stat_statements.max 1000 
pg_stat_statements.save on 
pg_stat_statements.track all 
random_page_cost 1.5 
server_encoding UTF8 
shared_buffers 128MB 
TimeZone Europe/Paris 
track_functions pl 
wal_buffers 1MB 
work_mem 8MB 

검색어 :

SELECT distinct 
    ((Table_Commande_Historique.COD_STECIAL 
    || ',' || Table_Commande_Historique.COD_MCIAL 
    || ',' || Table_Commande_Historique.NUM_REC_CLI 
    || ',' || Table_Commande_Historique.NUM_DNT_CLI 
    || ',' || Table_Commande_Historique.NUM_DDE)) cle 
FROM G1DDE2_DDE Table_Commande_Historique 
inner join "K2VER2_VER" ver 
    on (Table_Commande_Historique.NUM_REC_CLI 
     = (string_to_array(ver.num_cle,','))[3]::int 
    OR Table_Commande_Historique.NUM_DNT_CLI 
     = (string_to_array(ver.num_cle,','))[3]::int 
    OR ver.num_cle = (Table_Commande_Historique.COD_MCIAL 
        || ',' || Table_Commande_Historique.NUM_REC_CLI) 
    OR ver.num_cle = (Table_Commande_Historique.COD_MCIAL 
        || ',' || Table_Commande_Historique.NUM_DNT_CLI)); 

인덱스 :

CREATE INDEX idx_combo1 
    ON g1dde2_dde 
    USING btree 
    (((cod_mcial || ','::text) || num_rec_cli)); 

    CREATE INDEX idx_combo2 
    ON g1dde2_dde 
    USING btree 
    (((cod_mcial || ','::text) || num_dnt_cli)); 

    CREATE INDEX idx_dnt 
    ON g1dde2_dde 
    USING btree 
    (num_dnt_cli); 

    CREATE INDEX idx_rec 
    ON g1dde2_dde 
    USING btree 
    (num_rec_cli); 

    CREATE INDEX idx_k2ver3sb 
    ON "K2VER2_VER" 
    USING btree 
    (num_cle); 

가 EXPLAIN :

"HashAggregate (cost=197.97..201.77 rows=69 width=29)" 
" -> Nested Loop (cost=1.29..197.35 rows=248 width=29)" 
"  -> Seq Scan on "K2VER2_VER" ver (cost=0.00..2.58 rows=58 width=19)" 
"  -> Bitmap Heap Scan on g1dde2_dde table_commande_historique (cost=1.29..2.84 rows=5 width=29)" 
"    Recheck Cond: ((table_commande_historique.num_rec_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer) OR (table_commande_historique.num_dnt_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer) OR ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_rec_cli)::text)) OR ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_dnt_cli)::text)))" 
"    -> BitmapOr (cost=1.29..1.29 rows=5 width=0)" 
"     -> Bitmap Index Scan on idx_rec (cost=0.00..0.32 rows=2 width=0)" 
"       Index Cond: (table_commande_historique.num_rec_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer)" 
"     -> Bitmap Index Scan on idx_dnt (cost=0.00..0.32 rows=1 width=0)" 
"       Index Cond: (table_commande_historique.num_dnt_cli = ((string_to_array((ver.num_cle)::text, ','::text))[3])::integer)" 
"     -> Bitmap Index Scan on idx_combo1 (cost=0.00..0.32 rows=1 width=0)" 
"       Index Cond: ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_rec_cli)::text))" 
"     -> Bitmap Index Scan on idx_combo2 (cost=0.00..0.32 rows=1 width=0)" 
"       Index Cond: ((ver.num_cle)::text = (((table_commande_historique.cod_mcial)::text || ','::text) || (table_commande_historique.num_dnt_cli)::text))" 
+1

검색어, 표 및 색인을 표시하십시오. –

+1

설명을 표시하거나 추측해야합니까? –

+0

좋아, 그래서 나쁘지 않아. 행 수가 꽤 적습니다. 쿼리가 너무 많은 시간이 걸리는 데이터베이스의 설명입니까? –

답변

3
version PostgreSQL 8.4.4 

그게 문제입니다. 이 글을 읽을 보안 취약점과 버그 수정을 얻기 위해 약간의 방출을 고려하시기 바랍니다 :이 때로는 성능 문제를 소개 버그를 포함

http://www.postgresql.org/support/versioning/

. 당신이 얻을 것이 무엇 수정 검토하려면, 당신은 여기에 8.4.5 8.4.11에 노트로 볼 수 있습니다 :

http://www.postgresql.org/docs/8.4/static/release.html

램 기반의 설정 중 일부는 아마 너무 낮은, 그러나 얼마나 많은 RAM을 모른 채 시스템에 설치되어 있고 다른 곳에서 실행중인 것은 특정 번호를 제안 할 수있는 방법이 없습니다.

shared_buffers 128MB 

리눅스 전용 데이터베이스 서버에 대한 일반적인 조언은 아마도 최대 8GB로, 시스템의 전체 RAM의 25 %로 설정하고, 벤치마킹에 존재 기반에서 조정하는 것입니다.

effective_cache_size 1GB 

이 어떤 RAM을 할당하지만, 반복 비용 플래너는 여전히 동일한 쿼리에서 이전 읽기에서 캐시에있을 가능성이 얼마나되는지의 추정에 기초 파일에서 읽을 수 없습니다. shared_buffers 크기를 OS가 캐시 된 것으로 표시하는 것에 추가하는 것이 좋습니다.

work_mem 8MB 

이 것은 까다 롭습니다. 여러 가지 방법으로 성능을 쿼리하는 데 도움이 될 수 있지만 높은 값은 캐시에서 물건을 밀어내어 디스크 액세스를 증가시키는 경향이 있습니다. 또한 각 u 리가 여러 u 리 간격 (u 리 단계마다)을 여러 x 할당 할 수 있으 G로, 허용되는 연결 당이 크기의 할당을 일] 적으로 허용해야합니다. 이것은 하나의인데, 많은 수의 사용자를 제한된 수의 실제 데이터베이스 연결로 연결하기 위해 연결 풀을 사용하는 것이 종종 도움이되는 이유입니다. 더 큰 크기를 감당할 수 있다면 비트 맵 인덱스 스캔이 "손실"상태가되지 않도록하고 인덱스 조건을 다시 검사해야하기 때문에이 쿼리를 도울 수 있습니다.

cpu_tuple_cost을 설정하지 않았지만 일반적으로 기본 설정이 전반적으로 최상의 계획을 제시하기에는 너무 낮습니다. 큰 테이블에 90 개의 열이있는 것을 감안할 때이 값을 0.01에서 0.05로 높이는 것이 좋습니다.

effective_io_concurrency을 설정하지 않았 으면 도움이 될 것입니다. 다른 값으로 테스트 할 것입니다. (대안의 성능을 비교하는 테스트를 실행할 때 물론, 문제를 캐싱에 대한주의하십시오.)

maintenance_work_mem 128MB 

당신이 얼마나 많은 RAM에 따라,이 또는 합리적인 될 수도 있고 그렇지 않을 수도 있습니다. 즉각적인 문제는 영향을 미치지 않지만 자동 배수가 더 효율적으로 실행되고 인덱스 빌드가 더 빨리 실행되는 데 도움이됩니다.

checkpoint_segments 10 
wal_buffers 1MB 

그들은 즉각적인 문제의 일부가 아닌,하지만 그들은 여분의 디스크가 시간에 기록 될 수 있습니다, 그래서 아마 그들을 조정 지불 할 것입니다 :

이 아마 조금 낮다. wal_buffers은 컴퓨터의 RAM 용량이 매우 작은 경우가 아니라면 일반적으로 32MB입니다. checkpoint_segments은 더 이상 알지 못하면 예상하기가 어렵지만 로그와 통계를 확인하여 너무 자주 발생하는 체크 포인트가 발견되면 checkpoint_timeout을 기반으로 체크 포인트가 발생할 때까지 늘리십시오.

+0

'shared_buffers'에서'effective_io_concurrency'에 대한 언급과 정확한 오타가 추가되도록 편집되었습니다. – kgrittn

+0

그게 내가 필요한거야! 목요일에 결과를 다시 보겠습니다. 나는 지금 휴가 중이 야. 고마워. – Samson