2013-04-01 1 views
0

나는 this feature에 대해 말하고 있습니다. 내 문제를파티션 마스터 PostgreSQL 테이블의 효율적인 질의

logstore=# \d history_log_201304 
           Table "public.history_log_201304" 
    Column |   Type   |      
-----------+--------------------------+----------------------------------------------------------- 
id  | bigint     | NOT NULL DEFAULT nextval('history_log__id_seq'::regclass) 
tstamp | timestamp with time zone | NOT NULL DEFAULT now() 
session | character varying(40) | 
action | smallint     | NOT NULL 
userid | integer     | 
urlid  | integer     | 
Indices: 
    "history_log_201304_pkey" PRIMARY KEY, btree (id) 
    "history_log_201304_tstamp" btree (tstamp) 
    "history_log_201304_userid" btree (userid) 
Constraints: 
    "history_log_201304_tstamp_check" CHECK (tstamp >= '2013-04-01 00:00:00+04'::timestamp with time zone AND tstamp < '2013-05-01 00:00:00+04'::timestamp with time zone) 
Inherits: history_log 

그래서 무엇인가 - 나는 조건에 의해 제약을 한 쿼리를 수행 할 때

logstore=# \d history_log 
            Table "public.history_log" 
    Column |   Type   |      
-----------+--------------------------+----------------------------------------------------------- 
id  | bigint     | NOT NULL DEFAULT nextval('history_log__id_seq'::regclass) 
tstamp | timestamp with time zone | NOT NULL DEFAULT now() 
session | character varying(40) | 
action | smallint     | NOT NULL 
userid | integer     | 
urlid  | integer     | 
Indices: 
    "history_log__id_pkey" PRIMARY KEY, btree (id) 
Triggers: 
    insert_history_log_trigger BEFORE INSERT ON history_log FOR EACH ROW EXECUTE PROCEDURE history_log_insert_trigger() 

및 tstamp 열로 분할 된 아이 테이블 세트 :

나는 마스터 테이블이 자식 테이블에 직접 붙이기 - 매우 빠르게 작동합니다. 나는 마스터 테이블에 동일한 작업을 수행 할 때

logstore=# EXPLAIN SELECT userid FROM history_log_201304 WHERE tstamp >= (current_date - interval '3 days')::date::timestamptz AND tstamp < current_date::timestamptz AND action = 13; 
                 QUERY PLAN 
------------------------------------------------------------------------------------------------------------------------- 
Index Scan using history_log_201304_tstamp on history_log_201304 (cost=0.01..8.37 rows=1 width=4) 
    Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
    Filter: (action = 13) 

하지만 - 그것은 서열 검사로 이동 : 여기 무슨 일

logstore=# EXPLAIN SELECT userid FROM history_log WHERE tstamp >= (current_date - interval '3 days')::date::timestamptz AND tstamp < current_date::timestamptz AND action = 13; 
                    QUERY PLAN 

------------------------------------------------------------------------------------------------------------------------------------ 
--------------- 
Result (cost=0.00..253099.82 rows=1353838 width=4) 
    -> Append (cost=0.00..253099.82 rows=1353838 width=4) 
     -> Seq Scan on history_log (cost=0.00..0.00 rows=1 width=4) 
       Filter: ((action = 13) AND (tstamp < ('now'::cstring)::date) AND (tstamp >= ((('now'::cstring)::date - '3 days'::inte 
rval))::date)) 
     -> Index Scan using history_log_201203_tstamp on history_log_201203 history_log (cost=0.01..9.67 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201204_tstamp on history_log_201204 history_log (cost=0.01..9.85 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201205_tstamp on history_log_201205 history_log (cost=0.01..10.39 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201206_tstamp on history_log_201206 history_log (cost=0.01..10.32 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201207_tstamp on history_log_201207 history_log (cost=0.01..10.09 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201208_tstamp on history_log_201208 history_log (cost=0.01..10.35 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201209_tstamp on history_log_201209 history_log (cost=0.01..10.53 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201210_tstamp on history_log_201210 history_log (cost=0.01..11.83 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201211_tstamp on history_log_201211 history_log (cost=0.01..11.87 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201212_tstamp on history_log_201212 history_log (cost=0.01..12.40 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201301_tstamp on history_log_201301 history_log (cost=0.01..12.35 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201302_tstamp on history_log_201302 history_log (cost=0.01..12.35 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201303_tstamp on history_log_201303 history_log (cost=0.01..252959.45 rows=1353824 width= 
4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 
     -> Index Scan using history_log_201304_tstamp on history_log_201304 history_log (cost=0.01..8.37 rows=1 width=4) 
       Index Cond: ((tstamp >= ((('now'::cstring)::date - '3 days'::interval))::date) AND (tstamp < ('now'::cstring)::date)) 
       Filter: (action = 13) 

? 왜 마스터 테이블에 대한 쿼리가 빠른 속도가 아닌가?

나는 constraint_exclusionon으로 설정했습니다.

편집 : 우연히 해결책을 찾았습니다.

오늘까지 제약 조건이 잘못되었습니다. tstamp 열은 timestamp WITH time zone 유형이고 제약 조건은 timestamp WITHOUT time zone입니다. 필자는 쿼리에 형식 캐스트가 포함되도록 수정했으나 마스터 테이블에 대한 쿼리는 초 단위가 아닌 몇 분이 걸렸습니다. 그게 마지막 옵션 이었어. 그래서 내가 갔다. 대화를하는 동안 나는 DB에 가서 모든 자식 테이블에 EXPLAIN ANALYZE을 발행하여 실제 숫자를 얻었습니다. 그리고 그 후에 마스터 테이블에 대한 쿼리가 빨라졌습니다!

답변

1

쿼리 속도가 빨라야합니다. 마스터 테이블 에서 seq 스캔이 수행되고 있습니다. 올바르게 구성된 분할 된 테이블이 주어진 경우 에 행이 전혀 포함되지 않아야합니다 ().

EXPLAIN ANALYZE을 사용하면 검색어의 정확한 기간을 볼 수 있습니다. 둘 사이의 차이는 무시할 수 있어야합니다.


실제 결과는 결과를 반환하지 않는 하위 테이블에서 쿼리가 실행되는 것 같습니다. 아마도 귀하의 질문은 다음과 같습니다. CHECK 제약 조건을 충족시킬 수없는 자식 테이블이 여전히 검색되는 이유는 무엇입니까?

바로이 문제에 대해서는 a thread on the pgsql-bugs mailing list입니다. tstamp 열은 timestamp with time zone입니다. WHERE 절의 표현식은 시간 소인이 아닌 date 값이므로 점검을 사용할 수 없습니다. CURRENT_DATE 대신 CURRENT_TIMESTAMP을 사용하십시오. 자정 이후에 쿼리해야하는 경우 현재 쿼리를 유지하면서 tstamp 열 (::timestamp with time zone)과 동일한 유형으로 형변환을 추가하십시오.

+0

오래 걸립니다. 어떤 이유로 마스터 테이블에 행이 포함되어 있는지 확인할 수 있습니까? 나는 그것에 대한 모든 쿼리가 자식 테이블로 프록시 화된다고 믿는다 ... – skaurus

+0

@skaurus 쿼리는 실제로 각 테이블 (마스터 포함)에서 쿼리를 실행하고 그들 사이에 UNION ALL을 배치 한 것처럼 프록시된다. 아마도 시간이 걸리는 것은 실제 마스터 테이블에 대한 쿼리가 아니라 다른 하위 테이블에 대한 인덱스 스캔입니다. – cdhowie

+0

Errm ... 실제 숫자를 알려주기 위해 DB에 가서 모든 차일드 테이블에'EXPLAIN ANALYZE'를 발행했습니다 (합계로 약 2.5 초가 걸렸습니다). 그때 나는 마스터 테이블에 같은 명령을 내 렸습니다 - 그리고 2 초도 걸렸습니다! 나는 당황 스럽다. 몇 시간 전에도 사실이 아니 었습니다. 작은 배경 - 오늘까지는'timestamp WITHOUT time zone'을 가진 각 테이블에 제약 조건이 있었지만 방금 고쳤습니다. 그러나 변경 사항을 보지 못했습니다 (마스터 테이블에서 EXPLAIN ANALYZE가 거의 내 응용 프로그램을 죽였습니다). 그래서 제가 도움을 청하기로 결정했습니다. 그리고 지금 - 모두 좋다. 모든 자식 테이블에 대한 ANALYZE가 필요했습니다 :-) 감사합니다! – skaurus

관련 문제