我创建了一个这样的主表(例如简化):
CREATE TABLE mytable ( user_id integer,year integer,CONSTRAINT pk_mytable PRIMARY KEY (user_id,year) );
和10个分区表:
CREATE TABLE mytable_0 () INHERITS (mytable); CREATE TABLE mytable_1 () INHERITS (mytable); ... CREATE TABLE mytable_9 () INHERITS (mytable);
我知道将始终使用唯一的user_id条件从应用程序访问行.
所以我想使用基于user_id的规则在10个表中“相当”地传播数据.
ALTER TABLE mytable_0 ADD CONSTRAINT mytable_user_id_check CHECK (user_id % 10 = 0); ALTER TABLE mytable_1 ADD CONSTRAINT mytable_user_id_check CHECK (user_id % 10 = 1); ...
问题是,当我使用user_id上的条件查询主表“mytable”时,Postgresql分析器检查所有表并且不受益于检查约束:
EXPLAIN SELECT * FROM mytable WHERE user_id = 12345; "Result (cost=0.00..152.69 rows=64 width=36)" " -> Append (cost=0.00..152.69 rows=64 width=36)" " -> Seq Scan on mytable (cost=0.00..25.38 rows=6 width=36)" " Filter: (user_id = 12345)" " -> Seq Scan on mytable_0 mytable (cost=0.00..1.29 rows=1 width=36)" " Filter: (user_id = 12345)" " -> Seq Scan on mytable_1 mytable (cost=0.00..1.52 rows=1 width=36)" " Filter: (user_id = 12345)" ... " -> Seq Scan on mytable_9 mytable (cost=0.00..1.52 rows=1 width=36)" " Filter: (user_id = 12345)"
如果我使用这样的经典CHECK CONSTRAINT(以及与该规则匹配的重新分区):
ALTER TABLE mytable_0 ADD CONSTRAINT mytable_user_id_check CHECK (user_id BETWEEN 1 AND 10000); ALTER TABLE mytable_1 ADD CONSTRAINT mytable_user_id_check CHECK (user_id BETWEEN 10001 AND 20000); ...
它将仅扫描与条件匹配的表(在此示例中为mytable和mytable_1):
"Result (cost=0.00..152.69 rows=64 width=36)" " -> Append (cost=0.00..152.69 rows=64 width=36)" " -> Seq Scan on mytable (cost=0.00..25.38 rows=6 width=36)" " Filter: (user_id = 12345)" " -> Seq Scan on mytable_1 mytable (cost=0.00..1.52 rows=1 width=36)" " Filter: (user_id = 12345)"
但是使用这样的检查约束很难维护,因为将在表中填充的用户范围将在多年内发生变化.在不久的将来,成千上万,可能是数百万甚至更多……
我可以使用什么规则在10个表上平均分配我的数据,这些表可以受益于检查约束,以便主表上的SELECT只扫描正确的表…?
谢谢,
尼科
解决方法
http://www.postgresql.org/docs/9.1/static/ddl-partitioning.html
你提到的有两件事需要考虑.
首先,您说所有访问都将通过主键进行.这意味着您将不会从分区中获得任何性能优势(至少在正常使用情况下不会).每个分区的索引都会更小,但PG需要先选择要检查的分区.如果您需要重新索引或类似的话,您将获得的收益 – 您可以单独重新索引每个分区.
其次,你说你可能有数千到数十亿行.这让我得出两个结论:
>或许可以将决定留待以后.等到你需要分区.
>你不太可能想要10个分区,分别有两千行和二十亿个.
如果要进行分区,请按范围进行分区 – 比如100,000行或每个分区100万行.添加一个cron-job来检查所使用的最大ID,并在需要时创建一个新分区(也许每天一次).
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。