나는 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_exclusion
을 on
으로 설정했습니다.
편집 : 우연히 해결책을 찾았습니다.
오늘까지 제약 조건이 잘못되었습니다. tstamp
열은 timestamp WITH time zone
유형이고 제약 조건은 timestamp WITHOUT time zone
입니다. 필자는 쿼리에 형식 캐스트가 포함되도록 수정했으나 마스터 테이블에 대한 쿼리는 초 단위가 아닌 몇 분이 걸렸습니다. 그게 마지막 옵션 이었어. 그래서 내가 갔다. 대화를하는 동안 나는 DB에 가서 모든 자식 테이블에 EXPLAIN ANALYZE
을 발행하여 실제 숫자를 얻었습니다. 그리고 그 후에 마스터 테이블에 대한 쿼리가 빨라졌습니다!
오래 걸립니다. 어떤 이유로 마스터 테이블에 행이 포함되어 있는지 확인할 수 있습니까? 나는 그것에 대한 모든 쿼리가 자식 테이블로 프록시 화된다고 믿는다 ... – skaurus
@skaurus 쿼리는 실제로 각 테이블 (마스터 포함)에서 쿼리를 실행하고 그들 사이에 UNION ALL을 배치 한 것처럼 프록시된다. 아마도 시간이 걸리는 것은 실제 마스터 테이블에 대한 쿼리가 아니라 다른 하위 테이블에 대한 인덱스 스캔입니다. – cdhowie
Errm ... 실제 숫자를 알려주기 위해 DB에 가서 모든 차일드 테이블에'EXPLAIN ANALYZE'를 발행했습니다 (합계로 약 2.5 초가 걸렸습니다). 그때 나는 마스터 테이블에 같은 명령을 내 렸습니다 - 그리고 2 초도 걸렸습니다! 나는 당황 스럽다. 몇 시간 전에도 사실이 아니 었습니다. 작은 배경 - 오늘까지는'timestamp WITHOUT time zone'을 가진 각 테이블에 제약 조건이 있었지만 방금 고쳤습니다. 그러나 변경 사항을 보지 못했습니다 (마스터 테이블에서 EXPLAIN ANALYZE가 거의 내 응용 프로그램을 죽였습니다). 그래서 제가 도움을 청하기로 결정했습니다. 그리고 지금 - 모두 좋다. 모든 자식 테이블에 대한 ANALYZE가 필요했습니다 :-) 감사합니다! – skaurus