2010-06-19 98 views
3

我建立了一套%的文档分区表的http://www.postgresql.org/docs/8.1/interactive/ddl-partitioning.html如何在分区表中插入和选择数据?

CREATE TABLE t (year, a); 
CREATE TABLE t_1980 (CHECK (year = 1980)) INHERITS (t); 
CREATE TABLE t_1981 (CHECK (year = 1981)) INHERITS (t); 
CREATE RULE t_ins_1980 AS ON INSERT TO t WHERE (year = 1980) 
    DO INSTEAD INSERT INTO t_1980 VALUES (NEW.year, NEW.a); 
CREATE RULE t_ins_1981 AS ON INSERT TO t WHERE (year = 1981) 
    DO INSTEAD INSERT INTO t_1981 VALUES (NEW.year, NEW.a); 

从我的理解,如果我INSERT INTO T(一年一)VALUES(1980,5),它会去t_1980,和如果我插入t(year,a)VALUES(1981,3),它将转到t_1981。但是,我的理解似乎是不正确的。首先,我无法理解文档中的以下内容

“目前还没有简单的方法来指定行不能插入主表中。主表上的CHECK(false)约束将被所有的子表,所以不能用于此目的,一种可能是在主表上设置一个总是引发错误的ON INSERT触发器(或者,这样的触发器可以用来将数据重定向到合适的子表,而不是使用上面建议的一组规则。)“

以上是否意味着尽管设置了CHECK约束和RULE,我还必须在主表上创建TRIGGER,以便INSERT去正确的表?如果是这样的话,db支持分区的要点是什么?我可以自己设置单独的表格吗?我在主表中插入了一堆值,这些行仍在主表中,而不在继承的表中。

第二个问题。当检索行时,是从主表中选择,还是必须根据需要从各个表中进行选择?以下工作如何?

SELECT year, a FROM t WHERE year IN (1980, 1981); 

更新:好像我已经找到了答案,以我自己的问题

“请注意,COPY命令将忽略规则,如果你正在使用COPY中插入数据,你必须复制数据插入到正确的子表中而不是放入父项中COPY确实触发了触发器,因此如果使用触发器方法创建分区表,则可以正常使用它。

我的确在使用COPY FROM加载数据,所以RULEs被忽略。将尝试使用TRIGGER。

回答

3

肯定尝试触发器。

如果你认为你想实现一个规则,不要(唯一想到的例外是可更新的视图)。请参阅此great article by depesz以了解更多解释。

实际上,Postgres只支持事物读取的分区。您将自己设置插入分区的方法 - 大多数情况下为TRIGGERing。根据需要和应用程序,教您的应用程序直接插入分区有时会更快。

从分区表中选择时,只要您的CHECK约束条件已正确设置(您的示例中为正确设置)并且constraint_exclusion参数设置为正确,那么只需在主表上选择... WHERE ...即可。

对于8.4:

SET constraint_exclusion = partition; 

对于< 8。4:

SET constraint_exclusion = on; 

所有这一切被说,我其实很喜欢Postgres的做法,并经常使用它。

1

上面是否意味着,尽管 建立CHECK约束和 规则,我也有在主表,以便 嵌件到正确的表上创建触发器 ?

是的。阅读point 5 (section 5.9.2)

如果是这样的话,这将是 数据库支持 分割点?我可以自己设置 单独的表格吗?

基本上:子表中的INSERTS必须显式地完成(或者创建TRIGGERS,或者通过在查询中指定正确的子表)。但分区 对于SELECTS是透明的,并且(考虑到该模式的存储和索引优势)就是重点。 (此外,因为分区表是继承的,所以该模式从父代继承,因此一致性 被强制执行)。

1

触发器优于规则。 今天我玩了物化视图表的分区,并遇到触发器解决方案的问题。 为什么? 我使用RETURNING和当前的解决方案返回NULL :) 但是这里的解决方案适用于我 - 纠正我,如果我错了。 1.我有3个插入了一些数据的表格,有一个包含 数据的视图(让我们称之为viewfoo)。 2.插入到最后一个表中具有触发器,该触发器通过INSERT INTO插入物化视图表 matviewtable SELECT * FROM viewfoo WHERE recno = NEW.recno; 这工作正常,我使用RETURNING recno; (recno是SERIAL类型 - 序列)。

物化视图(表格)需要分区,因为它是巨大的,根据我的测试, 在这种情况下SELECT至少要快10倍。 分区问题: *当前触发解决方案RETURN NULL - 所以我不能使用RETURNING recno。 (当前触发解决方案=在depesz页面解释的触发器)。

解决方案: 我已经改变了我的第三台的触发不插入到物化视图表(该表是分区表的母公司),但创造了新的触发器,它直接插入 分区表从第3表和触发器回新。 物化视图表被自动更新并且RETURNING recno正常工作。 如果这有助于任何人,我会很高兴。

相关问题