我說的是this feature。高效查詢分區大師PostgreSQL表
我有主表:
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=# \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
那麼,什麼是我的問題 - 當我這樣做已經WHERE條件的制約查詢直接在子表上直接顯示 - 工作速度非常快。
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
。我修正了這個問題,修復了我的查詢以進行類型轉換 - 但仍然向master表查詢花費了幾分鐘而不是秒。這是我的最後一個選擇,所以我去了。在談話我去DB併發出EXPLAIN ANALYZE
所有子表得到一些實際的數字 - 這對查詢主表後成爲快!
它需要年齡。我如何檢查由於某種原因我的主表是否仍然包含行?我相信所有對它的查詢都會被代理到子表... – skaurus
@skaurus查詢確實是代理的,就好像你已經在每個表(包括主表)上執行查詢並在它們之間放置了'UNION ALL'。可能花費時間的不是實際主表上的查詢,而是其他子表上的索引掃描。 – cdhowie
Errm ...只是爲了給我一些實際的數字,我去了DB並向所有childs表發佈了「EXPLAIN ANALYSE」(總共耗時約2.5秒);然後我向主表發出了相同的命令 - 並且也花了2秒鐘!我很尷尬。即使在幾個小時前,情況並非如此。小背景 - 直到今天,我在每張桌上都有'timestamp without time zone'的約束,我剛剛修復了它 - 但沒有看到任何更改(主表上的EXPLAIN ANALYSE幾乎殺死了我的應用程序)。這就是我決定尋求幫助的原因。現在 - 一切都很好。似乎需要所有子表的ANALYZE :-)謝謝! – skaurus