一、分区表产生的背景
随着使用时间的增加,数据库中的数据量也不断增加,因此数据库查询越来越慢。
加速数据库的方法很多,如添加特定的索引,将日志目录换到单独的磁盘分区,调整数据库引擎的参数等。这些方法都能将数据库的查询性能提高到一定程度。
对于许多应用数据库来说,许多数据是历史数据并且随着时间的推移它们的重要性逐渐降低。如果能找到一个办法将这些可能不太重要的数据隐藏,数据库查询速度将会大幅提高。可以通过DELETE来达到此目的,但同时这些数据就永远不可用了。
因此,需要一个高效的把历史数据从当前查询中隐藏起来并且不造成数据丢失的方法。本文即将介绍的数据库表分区即能达到此效果。
二、分区表结构图
数据库表分区把一个大的物理表分成若干个小的物理表,并使得这些小物理表在逻辑上可以被当成一张表来使用。
-
主表
/父表
/Master Table
该表是创建子表的模板。它是一个正常的普通表,但正常情况下它并不储存任何数据。 -
子表
/分区表
/Child Table
/Partition Table
这些表继承并属于一个主表。子表中存储所有的数据。主表与分区表属于一对多的关系,也就是说,一个主表包含多个分区表,而一个分区表只从属于一个主表
三、PostgreSQL各个版本 的分区表功能
分区表在不同的文档描述中使用了多个名词:原生分区 = 内置分区表 = 分区表。
PostgreSQL 9.x 之前的版本提供了一种“手动”方式使用分区表的方式,需要使用继承 + 触发器的来实现分区表,步骤较为繁琐,需要定义附表、子表、子表的约束、创建子表索引,创建分区删除、修改,触发器等。
PostgreSQL 10.x 开始提供了内置分区表(内置是相对于 10.x 之前的手动方式)。内置分区简化了操作,将部分操作内置,最终简单三步就能够创建分区表。但是只支持范围分区(RANGE)和列表分区(LIST),
PostgreSQL 11.x 版本添加了对 HASH 分区。
本文将使用 PostgreSQL 10.x 版本及后续版本中的的内置分区表的使用方式,通过三步来创建分区表
1,创建父表------------指定分区键、分区策略(RANGE | LIST | HASH(11.x 才提供HASH策略))
2,创建分区表----------指定父表,分区键范围(分区键范围重叠之后会直接报错)
3,在分区上创建索引-----通常分区键上的索引是必须的
四、几种分区策略
PostgreSQL内置支持以下3种方式的分区:
1、范围(Range )分区:表被划分为由键列或列集定义的“范围”,分配给不同分区的值的范围之间没有重叠。例如:可以按日期范围或特定业务对象的标识符范围,来进行分区。
2、列表(List)分区:通过显式列出哪些键值出现在每个分区中来对表进行分区。
3、哈希(Hash)分区:(自PG11才提供HASH策略)通过为每个分区指定模数和余数来对表进行分区。每个分区将保存行,分区键的哈希值除以指定的模数将产生指定的余数。
五、建立分区实例
1、创建父表
CREATE TABLE measurement ( city_id int not null, logdate date not null, peaktemp int, unitsales int ) PARTITION BY RANGE (logdate);
2、创建分区表
CREATE TABLE measurement_y2007m11 PARTITION OF measurement FOR VALUES FROM (‘2007-11-01‘) TO (‘2007-12-01‘); CREATE TABLE measurement_y2007m12 PARTITION OF measurement FOR VALUES FROM (‘2007-12-01‘) TO (‘2008-01-01‘) TABLESPACE fasttablespace; CREATE TABLE measurement_y2008m01 PARTITION OF measurement FOR VALUES FROM (‘2008-01-01‘) TO (‘2008-02-01‘)
3、创建索引
CREATE INDEX ON measurement (logdate);
4、确保 postgresql.conf 中的 enable_partition_pruning (分区修剪)启用,否则,查询将不会被优化。
如果不进行分区修剪,上述查询将扫描父表 measurement 的每个分区。启用分区修剪后,计划器将检查每个分区的定义并证明不需要扫描该分区,因为该分区不能包含满足查询的WHERE子句的任何行。当计划器可以证明这一点时,它将从查询计划中排除(修剪)该分区。
5、维护分区
Analyze measurement