子分区表中的常量列

Posted

技术标签:

【中文标题】子分区表中的常量列【英文标题】:Constant column in child partition tables 【发布时间】:2014-02-14 07:32:49 【问题描述】:

我们在应用程序中使用基于继承的分区。分区在列上,这样每个分区对于该列都有不同的值。像这样的:

CREATE TABLE base(
    tblock INT NOT NULL,
    -- other fields --
);

-- Create a partition
CREATE TABLE partition_1(
    CHECK(tblock=1),
    INHERITS base
);

有很多这样的分区,每个分区都有大量的记录(以百万计)。整体数据库大小以 TB 为单位。

在上述模式中,分区必须有一个列 tblock,即使每个分区在所有行中都有该列的常量值。这显然是在浪费磁盘空间。

有没有办法声明分区,这样它就不会在磁盘上实际存储 tblock 的值?

我们目前使用的是 Postgresql 9.2.6。

【问题讨论】:

除非有一些 other 键也专门标识哪个分区中的内容。你怎么知道哪一行得到了哪个 tblock? @CraigRinger tblock 确定每行进入哪个分区,并在 WHERE 子句中用于约束排除。这意味着时间阻塞。没有其他钥匙。当然,数据结构比显示的要复杂一些。 好的,所以应用程序有办法知道感兴趣的行的“tblock”是什么?如果是这样,请考虑让应用程序直接查询分区,而不是依赖约束排除;这样你就不再需要 tblock 字段了。 @CraigRinger 谢谢。这是可能的,但非常痛苦。查询通常跨越很多分区。不过,我们确实将它用于某些查询类型。 我没有看到任何简单的解决方案。 Pg 的分区非常原始。嘿,我们正在寻找感兴趣的人来为更好的分区解决方案做出贡献....渴望深入了解源代码? ;-) 【参考方案1】:

当然,您可以编写会跳过某些列的触发器,但如果这样做,您将失去分区 (constraint exclusions) 带来的好处

如果表是继承的,则不能删除此列

这里有一些例子

create table base(i integer, j integer);
CREATE TABLE
create table inh_1() inherits (base);
CREATE TABLE
create table inh_2() inherits (base);
CREATE TABLE

CREATE OR REPLACE FUNCTION part_trigger()
RETURNS TRIGGER AS $$
BEGIN
if NEW.j = 1 THEN INSERT INTO inh_1 (i) VALUES (NEW.i);
    ELSIF NEW.j = 2 THEN INSERT INTO inh_2 (i) VALUES (NEW.i);
    END IF;
    RETURN NULL;
END;
$$
LANGUAGE plpgsql;
CREATE FUNCTION

CREATE TRIGGER insert_base
    BEFORE INSERT ON base
    FOR EACH ROW EXECUTE PROCEDURE part_trigger();
CREATE TRIGGER


insert into base values (100,1);
INSERT 0 0
insert into base values (140,2);
INSERT 0 0
sebpa=# select * from base;
  i  | j
-----+---
 100 |
 140 |
(2 rows)

sebpa=# select * from inh_1;
  i  | j
-----+---
 100 |
(1 row)

sebpa=# select * from inh_2;
  i  | j
-----+---
 140 |
(1 row)

【讨论】:

感谢您的回答,但我们需要排除约束。 没有其他方法 :( 请记住,如果您想使用约束排除,您必须在“分区”列上使用“检查”

以上是关于子分区表中的常量列的主要内容,如果未能解决你的问题,请参考以下文章

Oracle 虚拟列 子分区 virtual column partition

将新分区添加到已分区的配置单元表

mysql5.7子分区可以是list的吗

第七节——分区表

截断具有许多子分区的表需要很长时间

Hive 中的动态分区 - 使用一个固定列进行分区的缺点