为什么不能创建分区表

时间:2018-05-02 09:56:50

标签: postgresql create-table database-partitioning postgresql-9.6

我正在尝试使用分区创建简单的表。

这是我的命令:

CREATE TABLE measurement (
    city_id         int not null,
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);

这是我得到的错误:

  

SQL错误[42601]:错误:“PARTITION”或其附近的语法错误

无法理解是问题..

我正在使用PostgreSQL 9.6.3

2 个答案:

答案 0 :(得分:3)

“声明性表分区”是具有added in PostgreSQL 10的分区,它是具有自己语法的DBMS的一流功能。

在早期版本中,使用“表继承”可以花更多的精力来达到相同的效果。有a page in the manual describing how to do this manually,总结为:

  1. 创建“主”表,所有分区将从该表继承。
  2. 创建几个从主表继承的“子”表。
  3. 将表约束添加到分区表以在每个分区中定义允许的键值。
  4. 对于每个分区,在键列上创建索引,以及您可能需要的任何其他索引。
  5. (可选)定义触发器或规则,以将插入主表的数据重定向到适当的分区。
  6. 确保在postgresql.conf中没有禁用constraint_exclusion配置参数。如果是这样,查询将不会根据需要进行优化。

为简化此操作,如果无法升级到版本10,则可以使用pg_partman之类的扩展名,它为您提供了用于设置和管理分区集的其他功能。

答案 1 :(得分:0)

以下是为9.6版本自动创建每月分区的示例,可能与其他版本兼容:

`----------Function to create partitions by system------------------
CREATE OR REPLACE FUNCTION schema.insert_function()
RETURNS TRIGGER
AS $$
DECLARE
partition_date TEXT;
partition_schema TEXT;
partition_name TEXT;
start_of_month TEXT;
end_of_month TEXT;
BEGIN
partition_date := to_char(NEW.created_dtm,'YYYY_MM');
partition_schema := 'temp';
partition_name := 'patition_name_' || partition_date;
start_of_month := to_char((NEW.created_dtm),'YYYY-MM'|| '-01');
end_of_month := to_char((NEW.created_dtm + interval '1 month'),'YYYY-MM'|| '-01');
IF NOT EXISTS
(SELECT 1
 FROM   information_schema.tables
 WHERE  table_name = partition_name
 AND table_schema = partition_schema)
THEN
EXECUTE 'CREATE TABLE '|| partition_schema ||' . '|| partition_name ||' (check (created_dtm >= ''' || start_of_month || ''' and created_dtm < ''' || end_of_month || ''' ), ' || 'LIKE master_schema.master_table  INCLUDING ALL) INHERITS (master_schema.master_table)';
EXECUTE format('ALTER TABLE %I.%I OWNER TO role1', partition_schema, partition_name);
EXECUTE format('GRANT SELECT ON TABLE %I.%I TO read_only_role', partition_schema, partition_name);
EXECUTE format('GRANT INSERT, SELECT, UPDATE, DELETE ON TABLE %I.%I TO read_write_role', partition_schema, partition_name);
EXECUTE format('CREATE INDEX ON %I.%I(column1, column2, column3)', partition_schema, partition_name);
EXECUTE format('CREATE UNIQUE INDEX ON %I.%I(column4)', partition_schema, partition_name);
........
RAISE NOTICE 'A partition has been created %.%', partition_schema, partition_name;
RAISE NOTICE 'All necessary indices are created on %.%', partition_schema, partition_name;
END IF;
EXECUTE format('INSERT INTO %I.%I VALUES($1.*)', partition_schema, partition_name) using NEW;
RETURN NULL;
END
$$
LANGUAGE plpgsql;

ALTER FUNCTION schema.insert_function()
OWNER TO super_user;

-----------------------------------------Trigger on master table--------------
CREATE TRIGGER insert_trigger
BEFORE INSERT
ON master_schema.master_table
FOR EACH ROW
EXECUTE PROCEDURE schema.insert_function();`