2013-09-05 3 views
1

아래 함수를 작성하여 회사의 회계 월 정의를 저장하는 아래 표와 함께 사용했지만 회계 월별로 데이터를 집계 할 때이 함수가 상당히 느린 것 같습니다. 누구든지 내가 물건을 빠르게 할 수있는 방법에 대한 몇 가지 조언을 줄 수 있습니까?Postgresql 기능 최적화 회계 월 날짜

편집 :이 기능으로 병목 현상이 여전히 발생합니다. 나는 보풀을 없애기 위해 그것을 다시 작성했지만, 내 쿼리에서 fiscal_months 테이블에 합류하는 것보다 훨씬 느립니다. 그러나 나는 여전히 사용의 편의를 위해 함수를 사용하기 때문에 여전히 그것을 사용하는 수십 개의 쿼리를 다시 작성할 필요가 없습니다.

$ BODY $ SELECT CASE 추출물 ($ 1 년) < 2008 THEN ($ 1 MONTH)의 압축 :: 정수 ELSE (AS RETURNS 정수 CREATE 또는 함수 get_fiscal_month (날짜) 교체 fiscal_months FROM SELECT 개월 WHERE 추출물 (년 $ 1) = 년 $ (1)> = 시작일와 $ (1) < = 종료일) END $ BODY $ 언어의 SQL 휘발성 비용 (100);

편집 5 월 6 일 : 2014 년

CREATE OR REPLACE FUNCTION get_fiscal_month(date) 
    RETURNS integer AS 
    $BODY$ 
    SELECT month FROM fiscal_months WHERE $1 >= start_date AND $1 <= end_date 
    $BODY$ 
LANGUAGE sql STABLE 
COST 1000; 

변경
1. 제거 CASE 날짜는 내가 어떤이없는 < 2008 (때 (재 작성 기능이 약간 더 빠를 수 있습니다) 2008 년 이전의 데이터)
2. 연도를 제외하고 연도 제외 = 연도를 제외했습니다 (불필요한 단계입니다)
3. 변경된 휘발성을 안정화
4. 변경 비용 100 1000

에 표 fiscal_months에게 NULL NOT ( 아이디 일련 NULL NOT, 년 정수 NULL NOT, 월 정수 NULL NOT, START_DATE 날짜 NULL NOT, 종료일 날짜를 CREATE , PRIMARY KEY (ID) fiscal_months_pkey CONSTRAINT, UNIQUE (년, 월) fiscal_months_ukey CONSTRAINT)

CREATE TABLE fiscal_months 
(
id serial NOT NULL, 
year integer NOT NULL, 
month integer NOT NULL, 
start_date date NOT NULL, 
end_date date NOT NULL, 
CONSTRAINT fiscal_months_pkey PRIMARY KEY (id), 
CONSTRAINT fiscal_months_ukey UNIQUE (year, month), 
CONSTRAINT fiscal_months_ukey_end UNIQUE (end_date), 
CONSTRAINT fiscal_months_ukey_start UNIQUE (start_date) 
) 

CREATE INDEX fiscal_months_index_bothdates 
    ON fiscal_months USING btree (start_date, end_date); 

CREATE INDEX fiscal_months_index_test2 
    ON fiscal_months USING btree (start_date); 

변경
1. SO 사용자로부터 아래 의견에 대한 색인이 추가되었습니다.

표 통계
순차적 스캔 48,018,264
연속 튜플 읽기 4006572336
인덱스 스 3251027 지수 튜플으로 불러 27236663
튜플 삽입 0
튜플은 0
튜플 삭제 0
튜플 HOT 업데이트 0 업데이트
라이브 튜플 86
데드 튜플 0
힙 블록 읽기 3047
힙 블록 (13 개)
인덱스 블록은 3,251,026 토스트 블록 읽기
토스트 블록이
토스트 색인 블록 읽기
토스트 인덱스 블록이
마지막 진공 히트 히트 히트 51266249
인덱스 블록 읽기 조회수 2014 23 : 47.709653-05
마지막 Autoanalyze 2014년 5월 5일 16시 47분 -05-05 16 : 46 : 최후의 자동 진공이
마지막 13 2014년 5월 6일 분석 54.087489-05
: 29.248862-05
테이블 크기는 8192 바이트
토스트 테이블 크기 없음
인덱스 크기 96 킬로바이트

예 데이터
년 월 시작일 종료일
---- ----- ---- ------ ---------
2014 1 "2014-01-24"
2014 2 "2014-01-25" "2014-02-21 "
2014 3"2014-02-22 ""2014-03-28 "
2014 4"2014-03- 29 ""2014년 4월 25일 "
2,014 5"2014년 4월 26일 ""2014-05-23 "
2,014 6"2014년 5월 24일 ""2014년 6월 27일 "

추신 PostgreSQL 8.3을 사용 중입니다.
p.s. 나는 PostgreSQL을 사용하고있다. 8.4

+1

'start_date'및 'end_date'필드 모두에 고유 색인을 추가하십시오. –

+1

else 절의 select 문이이 함수의 속도를 늦추는 원인입니다 ... 여기에있는 것처럼 두 문을 사용하지 않고 단일 선택으로 문을 변경하려고합니다. – Twelfth

+0

@ Twelfth : 어떻게 알 수 있습니까? 나는 당신을 의심하지 않습니다. 그러나 나는 배우고 싶습니다. – Pyrite

답변

0

나는 회사의 회계 월 정의를 저장하는 아래 테이블과 함께 사용되는 아래 함수를 작성했지만, 회계 기능별로 데이터를 집계 할 때이 함수는 상당히 느린 것 같다. 달. 누구든지 내가 물건을 빠르게 할 수있는 방법에 대한 몇 가지 조언을 줄 수 있습니까?

이 기능을 사용하는 방법에 문제가 있다고 생각합니다. 이 방법으로 데이터를 집계하는 경우 플래너가 fiscal_month()와 조인 할 수 없게됩니다.

IMO를 수행해야하는 경우data >= '2008-01-01' 인 경우에만 집계 쿼리 의 UNION 부분에서 fiscal_month()를 호출해야합니다. 이것을 함수로 캡슐화한다는 것은 인라인 할 수 없다는 것을 의미하며, 결과적으로 해시 조인을 할 수있는 대신, 문제가있는 곳에서 거의 확실하게 중첩 된 루프를 사용하게됩니다.

+0

위의 제 수정 된 게시물을 살펴 보겠습니다. 더 자세한 내용을 추가했습니다. – Pyrite

+0

예이 기능을 사용하여 집계 중입니다. 예 : SELECT get_fiscal_month (mydate) AS m, COUNT (*) AS v from sometablewithadate GROUP BY m ORDER BY m – Pyrite

2

해당 참조 테이블에있는 데이터는 무엇입니까? 회계 달은 일반적으로 조회에 의존하지 않는 날짜로부터 결정될 수 있습니다.

예를 들어, 회계 연도의 경우 2012 실행 2012년 4월 가입일 March 2013, 당신과 함께 현재의 회계 월 결정 :

to_char(date_trunc('month',current_date) - interval '3' month, 'YYYY MM') 

내가 (SQL에서 바람직하게는,이 방식으로 알고리즘을 구현 볼 것 2009 년에 회계 연도 논리가 변경된 것처럼 보이므로 CASE의 사용과 함께).

+0

예제 게시물을보기 위해 내 게시물을 편집/업데이트했습니다. 나는 당신이 제안한 것처럼 그것을 즉시 계산할 수 있는지 확신하지 못한다. – Pyrite