2014-11-12 5 views
0

임시 테이블을 만들려고 할 때 성능에 문제가 있습니다. Duration [0] in seconds=11 :이 기능을 실행하면, 내가 통지를 얻을 수 있기 때문에 http://explain.depesz.com/s/uerF
그것은, 이상하다 : 임시 테이블에 행 삽입

StartTime := clock_timestamp(); 
CREATE TEMP TABLE wo_tmp WITH (OIDS) AS 
SELECT workorders1_.woid AS w_id, workorders1_.woid4seg AS w_id4seg 
FROM common.workorders workorders1_ 
INNER JOIN common.lines lines2_ ON workorders1_.wolineid=lines2_.lineid 
INNER JOIN common.products products2_ ON workorders1_.woprodid=products2_.prodid 
INNER JOIN common.depts depts3_ ON lines2_.linedeptid=depts3_.deptid 
WHERE workorders1_.wostatus='F' 
    AND workorders1_.wotypestatus = ANY ('{R,C,I,D}'::text[]) 
AND (p_deptid = 0 OR (depts3_.deptid = p_deptid AND ((p_deptid = 5 AND workorders1_.wosegid = 1) OR workorders1_.wosegid = 4))) 
AND (p_lineid = 0 OR lines2_.lineid = p_lineid) 
AND (p_prodid = 0 OR products2_.prodid = p_prodid) 
    AND (p_nrkokili = 0 OR workorders1_.wonrkokili = p_nrkokili) 
    AND (p_accepted = TRUE OR workorders1_.worjacceptstatus = 'Y') 
    AND workorders1_.wodateleaverr BETWEEN p_dfr AND p_dto 
    AND lines2_.status <> 'D'; 

CREATE INDEX wo_tmp_w_id_idx 
    ON wo_tmp USING btree (w_id ASC NULLS LAST); 
CREATE INDEX wo_tmp_w_id4seg_idx 
    ON wo_tmp USING btree (w_id4seg ASC NULLS LAST); 

    EndTime := clock_timestamp(); 
    Delta := extract('epoch' from EndTime)::bigint - extract('epoch' from StartTime)::bigint; 
    RAISE NOTICE 'Duration [0] in seconds=%', Delta; 

가 여기에 explain analyze 보고서입니다 : 다음 코드는 plpgsql 기능의 일부입니다. 임시 테이블을 만들지 않고 쿼리를 확인하면 결과 시간은 ~300ms입니다.

임시 테이블에 레코드 (~ 73k)를 삽입하는 데 11 초가 걸릴 수 있습니까? 속도를 낼 수 있을까요?

+0

색인 생성에는 다소 시간이 걸릴 수도 있습니다. 프로 시저 내부의 모든 쿼리에 대해'EXPLAIN ANALYZE'를 실행하십시오. –

+0

나는 달렸지 만 임시 테이블 만 생성하는 데는 시간이 걸립니다. – bemol

+0

* 항상 * 중요한 정보 인 함수 머리글과 바닥 글을 포함하십시오. 또한 [8.4 페이지는 eol에 도달했으며 더 이상 지원되지 않습니다] (http://www.postgresql.org/support/versioning/). 현재 버전으로의 업그레이드를 긴급히 고려하십시오. –

답변

2

당신이 함수 내부에 임시 테이블을 채울 때, 하나 이상의 문제를 찾을 수 있습니다

  • 잠금 문제 - 모든 임시 테이블은 시스템 카탈로그의 일부 필드가있는 테이블. 이러한 테이블을 집중적으로 생성 및 삭제하면 많은 로킹으로 높은 오버 헤드가 발생합니다. 때로는 임시 테이블을 배열로 대체 할 수 있습니다. 그것은 당신의 경우가 아닙니다. 색인이 필요하기 때문입니다.

  • 블라인드 최적화 - PlpgSQL 함수의 내장 SQL은 PostgreSQL 9.2에서 약간 향상되었지만 (여전히 성능 문제가있을 수 있음) 현재 값에 최적화되어 있지 않습니다. . 일부 성능 문제는 그 다음 동적 SQL이 필요

  • 일부 하드웨어 또는 파일 시스템 문제이 문제 (onesecond)의 일부 링크 -.. 내가 도움 WITHOUT OIDS에 대해 조금 혼란 스러워요 그것은 파일 시스템과 같은 끔찍한 병목 임시 테이블은 파일 시스템 캐시에 저장됩니다 - 빠른 53K 행을 저장해야합니다. 4 바이트를 제거하면 (35에서) 너무 큰 변경되지 않습니다. 이 11 초 오버 헤드에 대한 이상한 있도록 시스템을 제기 할

    postgres=# create table t1 with (oids) as select 1 a,2 b,3 c from generate_series(1,73000); 
    SELECT 73000 
    Time: 302.083 ms 
    postgres=# create table t2 as select 1 a,2 b,3 c from generate_series(1,73000); 
    SELECT 73000 
    Time: 267.459 ms 
    postgres=# create temp table t3 with (oids) as select 1 a,2 b,3 c from generate_series(1,73000); 
    SELECT 73000 
    Time: 154.431 ms 
    postgres=# create temp table t4 as select 1 a,2 b,3 c from generate_series(1,73000); 
    SELECT 73000 
    Time: 153.085 ms 
    postgres=# \dt+ t* 
            List of relations 
        Schema | Name | Type | Owner | Size | Description 
    -----------+------+-------+-------+---------+------------- 
    pg_temp_2 | t3 | table | pavel | 3720 kB | 
    pg_temp_2 | t4 | table | pavel | 3160 kB | 
    public | t1 | table | pavel | 3720 kB | 
    public | t2 | table | pavel | 3160 kB | 
    (4 rows) 
    

쓰기 3메가바이트 파일은 1 초 ..보다 훨씬 작아야합니다. 추신. 기본 temp_buffers은 8MB이므로 결과는 메모리에만 저장해야하며 아마도이 가설은 거짓이며 더 많은 가능성이있는 것은 맹검 최적화 가설입니다.

+0

감사합니다. 아주 좋은 설명입니다. 귀하의 팁을 사용하고 알려 드리겠습니다. – bemol

+0

한 가지 더, 인덱스가 필요하지 않습니다. 다음 쿼리의 성능을 높이기 위해 사용했지만, 임시 테이블을 만드는 데 5 초가 덜 걸리는 경우 ~ 1 초를 희생 할 수 있습니다. Sry for english – bemol

+0

동적 쿼리로 변경하면 원하는만큼 성능이 향상되었습니다. 훌륭한 직업 @Pavel Stehule, 정말 고마워요. 당신은 나의 영웅이다. :) – bemol

1

처음에는 임시 테이블에 WITH (OIDS)을 사용하지 마십시오. 이제까지. 일반 테이블에서 OID를 사용하는 것은 바람직하지 않습니다. 그것은 임시 테이블에 대해 두 가지가됩니다. 또한 디스크의 RAM/공간을 줄여줍니다. WITHOUT OIDS으로 전환하십시오.

다음으로, 임시 테이블이 없어서 임시 테이블이 디스크로 유출 될 가능성이 높습니다. 디스크에 쓰기 방지하기 위해 충분히 관대 반올림 -

SELECT pg_size_pretty(pg_relation_size('wo_tmp')); 

으로 임시 테이블의 실제 크기를 확인하고 그에 따라 temp_buffers을 설정 가능 세션에 대해서만.

세부 사항 :

+0

감사합니다. 'OIDS없이'속도를 내주세요. – bemol

관련 문제