【问题标题】:postgres table partition on null date空日期的postgres表分区
【发布时间】:2013-03-05 09:15:44
【问题描述】:

我想知道这是否可能(以及如何去做)

在 postgres 9.1 中根据日期字段是否为空来对表进行分区。

非常有效,我有一个表,它变得非常大,我有一个“delete_on”日期,当项目被删除时,它们只会被标记为已删除。

这将是归档它们并保持活动表较小的理想选择。

我在考虑一个表分区,只是有类似的东西

活动(delete_on = NULL)

存档(deleted_on != NULL)

然后,当我对记录进行更新并将其设置为删除时,它将被写入存档表。

我可以手动完成,只需创建两个单独的表并编写代码来复制数据,但如果我可以直接将它放在数据库中,我会喜欢它。

有什么想法吗?

编辑:

主表

CREATE TABLE my_table (
    id              int not null,
    deleted         date not null,
    number1         int,
    number2         int
);

分区

CREATE TABLE my_table_active (
  CHECK (deleted IS NULL)
) INHERITS (my_table);
CREATE TABLE my_table_archive ( 
  CHECK (deleted IS NOT NULL)
) INHERITS (my_table);

触发函数

CREATE OR REPLACE FUNCTION my_table_insert_trigger()
RETURNS TRIGGER AS $$
BEGIN
    IF ( NEW.deleted IS NULL ) THEN
        INSERT INTO my_table_active VALUES (NEW.*);
    ELSE 
        INSERT INTO my_table_archive VALUES (NEW.*);

    END IF;
    RETURN NULL;
END;
$$
LANGUAGE plpgsql;

创建触发器

CREATE TRIGGER insert_my_table_trigger
    BEFORE INSERT ON my_table
    FOR EACH ROW EXECUTE PROCEDURE my_table_insert_trigger();

(我从 Postgres 文档中获取了以上内容)

如果您要对活动表中已经存在的字段进行更新,这将如何工作?

所以我在活动表中有一条记录(即删除为空),然后我将该记录设置为删除(通过给它一个日期戳)。那时我希望它移动到存档表。

【问题讨论】:

  • 那么状态要么是 NULL(即为空或未设置)要么是日期(记录被删除的日期),所以它在技术上不是布尔值。但是,更多地考虑这个问题我在想我什至需要打扰分区吗?使用 deleted_on 日期设置的记录越多,那么我只需优化我的查询以仅搜索已删除为 null 的记录,这不会使查询规划器只检查较小的记录集吗?

标签: postgresql postgresql-9.1


【解决方案1】:

您可以在IS NULLIS NOT NULL 上进行分区。

= NULL!= NULL 总是导致 NULL,所以它们冲突。你永远不会在 SQL 中写= NULL,总是a IS NULLa IS DISTINCT FROM b

有关如何设置 PostgreSQL 的基于表继承的分区和相关约束排除的详细信息,请参阅the documentation

在任何情况下都不需要“编写代码来复制数据”。在最坏的情况下,您需要编写一个简单的INSERT INTO newtable SELECT * FROM oldtable WHERE somefield IS NULL;

【讨论】:

  • 您好,非常感谢您提供的信息。我需要设置一个分区表还是需要设置一个触发器?我会用我认为我需要的“刺”来更新我原来的问题。
  • @Tada.wav 您可以让您的应用程序直接插入到分区中,或者让您的应用程序插入到顶级表中并获得一个触发器以将写入重定向到分区中。让应用直接写入分区效率更高,但需要应用了解分区方案,因此以后更难更改,因此大多数人使用触发器。
  • 嗨,如果可能的话,我更喜欢使用触发器,但我仍然不确定他们将如何处理更新。如果我在活动分区中有一个表并且我设置了它的删除日期,那么触发器如何知道将其从活动表中删除并将其写入存档分区?
  • @Tada.wav 见stackoverflow.com/q/1798209/398670。基本上,您UPDATE 顶级分区和BEFORE UPDATE ... FOR EACH ROW 触发器将更新或至少跨分区更新转换为DELETEINSERT。无论如何,这实际上是 PostgreSQL 更新在内部工作的方式,您只是在两个表之间进行。在 Pg 中进行分区比它应该的要困难得多,我们都希望改进它。最近有一些工作,所以运气好的话可能在 9.3 之后......
  • 感谢您的信息,我会将其标记为答案,因为它会导致解决方案。
猜你喜欢
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多