我有一个用于存储呼叫详细记录的数亿个行的小数据库。我按照以下方式设置分区:
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)
所以,我可以看到它不扫描所有分区,只扫描相关的分区(在索引扫描中非常快),还有主表(从我见过的例子中看起来很正常)。但是主表上的seq扫描的高成本似乎是异常的。我很乐意这样下来,我认为没有理由,特别是因为主表中没有任何记录:
cdrs=> select count(*) from only acmecdr;
count
-------
0
(1 row)
除非我遗漏了一些明显的东西,否则这个查询应该很快。但事实并非如此 - 大约需要2分钟?这似乎不正常(即使是慢速服务器)。
我不知道下一步该尝试什么,所以如果有人在正确的方向上有任何建议或指示,我们将非常感激。