我有一个包含几亿行的小数据库,用于存储呼叫详细记录。我按照以下方式设置分区:
http://www.postgresql.org/docs/9.1/static/ddl-partitioning.html
直到现在它似乎工作得很好。我有主表“acmecdr”,它具有插入正确分区的规则并检查约束以确保在选择数据时使用正确的表。以下是其中一个分区的示例:
cdrs=> \d acmecdr_20130811
Table "public.acmecdr_20130811"
Column | Type | Modifiers
-------------------------------+---------+------------------------------------------------------
acmecdr_id | bigint | not null default
...snip...
h323setuptime | bigint |
acmesipstatus | integer |
acctuniquesessionid | text |
customers_id | integer |
Indexes:
"acmecdr_20130811_acmesessionegressrealm_idx" btree (acmesessionegressrealm)
"acmecdr_20130811_acmesessioningressrealm_idx" btree (acmesessioningressrealm)
"acmecdr_20130811_calledstationid_idx" btree (calledstationid)
"acmecdr_20130811_callingstationid_idx" btree (callingstationid)
"acmecdr_20130811_h323setuptime_idx" btree (h323setuptime)
Check constraints:
"acmecdr_20130811_h323setuptime_check" CHECK (h323setuptime >= 1376179200 AND h323setuptime < 1376265600)
Inherits: acmecdr
现在,正如人们所期望SET constraint_exclusion = on
的那样,应该自动首选正确的分区,并且由于上面有索引,因此应该只进行一次索引扫描。
然而:
cdrs=> explain analyze select * from acmecdr where h323setuptime > 1376179210 and h323setuptime < 1376179400;
QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Result (cost=0.00..1435884.93 rows=94 width=1130) (actual time=138857.660..138858.778 rows=112 loops=1)
-> Append (cost=0.00..1435884.93 rows=94 width=1130) (actual time=138857.628..138858.189 rows=112 loops=1)
-> Seq Scan on acmecdr (cost=0.00..1435863.60 rows=1 width=1137) (actual time=138857.584..138857.584 rows=0 loops=1)
Filter: ((h323setuptime > 1376179210) AND (h323setuptime < 1376179400))
-> Index Scan using acmecdr_20130811_h323setuptime_idx on acmecdr_20130811 acmecdr (cost=0.00..21.33 rows=93 width=1130) (actual time=0.037..0.283 rows=112 loops=1)
Index Cond: ((h323setuptime > 1376179210) AND (h323setuptime < 1376179400))
Total runtime: 138859.240 ms
(7 rows)
所以,我可以看到它没有扫描所有分区,只有相关的分区(在索引扫描中并且非常快)以及主表(从我看到的示例中这似乎是正常的)。但是对master表进行seq扫描的高成本似乎是不正常的。我很乐意让它下来,我看不出有什么原因,特别是因为主表中没有任何记录:
cdrs=> select count(*) from only acmecdr;
count
-------
0
(1 row)
除非我遗漏了一些明显的东西,否则这个查询应该很快。但事实并非如此——大约需要 2 分钟?这似乎根本不正常(即使对于慢速服务器)。
我不知道接下来要尝试什么,所以如果有人对正确的方向有任何建议或指示,将不胜感激。