PostgreSQL分表(partition)文档学习笔记

0. 背景

博主有一批500G的轨迹数据文本文件,想用PG进行管理。新手上路第一天,手动建立了十几个表,用copy_from的方式导入数据,但导着导着速度越来越慢……发现对一个含1126万条数据的表(没有索引)执行count(*)耗时5min32s,绝了。搜到partiton这种方法,先死马当活马医吧。(貌似可以进一步分库,但只有一台机器搞啥分布式存储)
结果:
采用hash方法,将同样的数据分成32个表之后,查询耗时为5.1s;分成128个表后耗时4.1s。
PostgreSQL版本:12
涉及的文档:
5.11. Table Partitioning
CREATE TABLE
参考的博文:
PostgreSQL分区表(Table Partitioning)应用
一次难得的分库分表实践
PostgreSQL 最佳实践 - 水平分库(基于plproxy)
分库分表的基本思想

1. What & Why

1.1 What

什么是分表: 把一个大表分成若干分区,使其物理上分散,逻辑上连续。各分区继承一个母表,对母表进行的操作会自动同步到各分区(包括插入数据时按照分表方式自动导入不同分区、建立索引等)。

1.2 Why

单表数据量过大(对于博主8GRAM的商务本来说,千万级),影响查询性能。
分表的优点:

  • 显著提升查询性能,尤其是当频繁访问的记录在同一个分区或少数几个分区中时。
  • 分区索引在一定程度上替代了传统的索引,可以减小索引占用的空间。
  • 批量读取和删除可以以分区为单位完成,例如detach partition这种操作速度远远快于bulk delete操作。

2. PostgreSQL分表方式

  • Range Partitioning
    将某列(或某几列)的值划分成互不重叠的区间,如时间按月划分。
  • List Partitioning
    按枚举出的一些值分区。
  • Hash Partitioning
    指定一个模数(modulus),将hash值对模取余(remainder),余数相同的分到同一分区。

range、list方式可能会出现数据不均匀的情况,如冰棍销售情况按月分表,夏天销量远高于冬天。

3. 官方文档中的示例

3.1 创建分区表

  • by range
-- 创建母表
CREATE TABLE measurement (
    logdate         date not null,
    peaktemp        int,
    unitsales       int
) PARTITION BY RANGE (logdate);
--创建分区
CREATE TABLE measurement_y2016m07
    PARTITION OF measurement (
    unitsales DEFAULT 0
) FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');
  • by hash
-- 创建母表
CREATE TABLE orders (
    order_id     bigint not null,
    cust_id      bigint not null,
    status       text
) PARTITION BY HASH (order_id);
-- 创建分区(以4为模数,按余数分4个区)
CREATE TABLE orders_p1 PARTITION OF orders
    FOR VALUES WITH (MODULUS 4, REMAINDER 0);
CREATE TABLE orders_p2 PARTITION OF orders
    FOR VALUES WITH (MODULUS 4, REMAINDER 1);
CREATE TABLE orders_p3 PARTITION OF orders
    FOR VALUES WITH (MODULUS 4, REMAINDER 2);
CREATE TABLE orders_p4 PARTITION OF orders
    FOR VALUES WITH (MODULUS 4, REMAINDER 3);

3.2 创建索引

对母表进行操作即可,已存在的分区和后续创建的分区上也会包含该索引。

CREATE INDEX ON measurement (logdate);

3.3 删除分区

可以快速删除数以百万计的数据。

DROP TABLE orders_p4;

但通常使用另一种方式(detach):将分区分离出来作为独立的表,可以在删除前进行备份、聚合、统计等操作。

ALTER TABLE orders DETACH PARTITION orders_p4;

4. 注意事项

4.1 在哪些列上建立分区

经常出现在WHERE子句中的列(或多个列)适合。这样可以快速排除掉不相关的分区。此外,将分区作为整体进行删除非常快,所以如果有能一起移除的数据可以放在同一个分区(如业务数据按时间分区)。

4.2 分区数量

分区数量过多或过少都会影响性能。分区数量过多会导致planning time变长(可用explain命令查看,参考)、内存开销变大。(文档原文:可以很好地处理a few thousand个分区)
使用hash方法时建议为2的倍数,这样未来如果有分区过大需要进一步分区时,可以直接分裂分区,而不需要将数据跨分区迁移。

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Oracle数据库中可以使用分表来提高性能和管理大量数据。下面是一些常见的分表策略: 1. 范围分区:根据列的范围将数据分布到不同的分区中。例如,按照日期范围将数据分为每个月或每年的分区。 2. 列值分区:根据列的值将数据分布到不同的分区中。例如,根据地区将数据分区,使得每个分区只包含特定地区的数据。 3. 列列表分区:根据多个列的值组合将数据分布到不同的分区中。例如,根据地区和部门将数据分区,以实现更细粒度的数据管理。 4. 哈希分区:根据哈希函数将数据分布到不同的分区中。这种方法可以确保数据在各个分区中均匀分布,适用于负载均衡和并行查询。 5. 范围-哈希混合分区:结合范围和哈希方法进行分区,以实现更灵活的数据管理。 在创建表时,可以使用`PARTITION BY`子句指定分区策略,并定义分区键和分区数。例如: ``` CREATE TABLE my_table ( id NUMBER, name VARCHAR2(50), created_date DATE ) PARTITION BY RANGE (created_date) ( PARTITION p1 VALUES LESS THAN (TO_DATE('2023-01-01', 'YYYY-MM-DD')), PARTITION p2 VALUES LESS THAN (TO_DATE('2024-01-01', 'YYYY-MM-DD')), PARTITION p3 VALUES LESS THAN (MAXVALUE) ); ``` 上述示例使用了范围分区,根据`created_date`列的值将数据分布到不同的分区中。 请注意,分表需要谨慎规划和设计,以确保最佳性能和可维护性。在选择分区策略时,应考虑数据量、查询模式和维护操作的影响。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值