代码之家  ›  专栏  ›  技术社区  ›  punkish

如何插入和选择带分区表的数据?

  •  3
  • punkish  · 技术社区  · 15 年前

    我在以下位置为每个文档设置了一组分区表: 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);
    

    据我所知,如果我把t(年,a)值(1980年,5年)插入t_1980年,如果我把t(年,a)值(1981年,3年)插入t_1981年。但是,我的理解似乎不正确。首先,我无法从文档中了解以下内容

    “目前没有简单的方法来指定不能将行插入主表中。主表上的check(false)约束将由所有子表继承,因此不能用于此目的。一种可能是在主表上设置一个总是引发错误的on-insert触发器。(或者,可以使用此类触发器将数据重定向到适当的子表中,而不是使用上面建议的一组规则。)

    上面的意思是,尽管设置了检查约束和规则,我还是必须在主表上创建触发器,以便插入到正确的表中?如果是这种情况,那么支持分区的DB的意义是什么?我可以自己安排单独的桌子吗?我在主表中插入了一组值,这些行仍然在主表中,而不是在继承的表中。

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

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

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

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

    我确实使用了copy-from来加载数据,所以规则被忽略了。将尝试使用触发器。

    3 回复  |  直到 13 年前
        1
  •  3
  •   rfusca    15 年前

    一定要试试触发器。

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

    实际上,Postgres只支持在事物的阅读端进行分区。您将自己设置插入分区的方法——在大多数情况下是触发。根据需要和应用程序,有时可以更快地教会应用程序直接插入到分区中。

    当从分区表中选择时,您确实可以选择…哪里。。。在主表上,只要检查约束设置正确(在示例中),并且约束的排除参数设置正确。

    8.4:

    SET constraint_exclusion = partition;
    

    对于& 8.4;

    SET constraint_exclusion = on;
    

    尽管如此,我真的很喜欢Postgres的方式,并且经常自己使用它。

        2
  •  1
  •   leonbloy    15 年前

    以上是否意味着尽管 设置检查约束和 规则,我也必须创建 在主表上触发,以便 插入到正确的表格?

    对。读 point 5 (section 5.9.2)

    如果是这样的话,会是什么 数据库支持点 分区?我可以设置 把桌子分开?

    基本上:子表中的插入必须显式完成(创建触发器,或者通过在查询中指定正确的子表)。但是分割 对于选择是透明的(考虑到这个模式的存储和索引优势),这就是重点。 (此外,因为分区表是继承的, 模式继承自父级,因此一致性 被强制执行)。

        3
  •  1
  •   Zeljan Rikalo    13 年前

    触发器显然比规则好。 今天,我已经开始对物化视图表进行分区,并遇到了触发器解决方案的问题。 为什么? 我正在使用返回,当前解决方案返回空:) 但这里有一个适合我的解决方案-如果我错了,请纠正我。 1。我有3个表,其中插入了一些数据,有一个视图(我们称之为viewfoo),其中包含 需要具体化的数据。 2。插入到最后一个表中具有插入到物化视图表中的触发器 通过插入MatviewTable,从viewfoo中选择*,其中recno=new.recno; 这很好,我用的是返回的recno;(recno是序列类型sequence)。

    物化视图(表)需要分区,因为它很大,并且 根据我的测试,在这种情况下,选择它至少要快x10。 分区问题: *当前触发器解决方案返回空-因此我不能使用返回的recno。 (当前触发器解决方案=在DEPESZ页上解释的触发器)。

    解决方案: 我已经将第三个表的触发器更改为不插入物化视图表(该表是分区表的父表),而是创建了新的触发器来插入 直接从第三个表分区表,该触发器返回new。 物化视图表自动更新,返回recno工作正常。 如果这对任何人都有帮助,我会很高兴的。