在数据库日渐庞大的今天,为了方便对数据库数据的管理,比如按时间、地区去统计一些数据时,基数 过于庞大带来了诸多不便。很多商业数据库都提供分区的概念,按不同的维度去存放数据,便于后期的 管理,OushuDB也不例外。
表分区是把逻辑上的一个大表拆分成多个子表,这样不仅能带来访问速度的提升,更能带来管理和维护 上的方便,
这样的话,有两个好处:
查询优化器可以针对分区表进行优化,如果查询只涉及到某些分区,则查询计划只需要扫描
这些分区,从而加速查询
如果我们按照日期进行分区的话,我们可以简单的加入分区和删除过期的分区。
分区表的目的是为了提高查询性能,但并非所有的表都适合做分区。只有大型事实表、经常使用特定>条 件[日期、地区等]查询数据、维护历史数据、数据分布均匀的情况,可通过分区策略大大提升使用性 能。且分区数不宜过多,否则会影响维护和管理工作速度。
OushuDB支持基于Range和List的两种分区方式:
Range分区:表被一个或者多个关键列分区成”范围”,这些范围在不同的分区里没有重叠。 比如依 据日期、价格数值范围进行分区。 List分区:依据一个值的列表进行分区,比如依据地区列表进行分区。
创建新的分区表使用CREATE TABLE ... PATITION BY语法实现,创建分区表步骤如下:
1. 确定分区类型:范围分区RANGE或列表分区List。
2. 选定分区字段:范围分区多为日期、数值类型字段;列表分区多为枚举类型的特定列表;
3. 确定分区级别:OushuDB支持子分区SUBPARTITION,可以按照不同维度实现多级分区。
定义Range分区
比如,假设我们为一个巨大的冰激凌公司构造数据库。该公司每天都测量最高温度,以及每个地区的冰 激凌销售。且大多数查询都只会访问最后一周,最后一个月或者最后一个季度的数据,因为这个表的主 要用途是为管理准备在线报告。为了减少需要存储的旧数据,我们决定只保留最近三年的有用数据。在 每个月的开头,我们都会删除最旧的一个月的数据。因此,我们会选定日期字段作按月的范围分区:
|
CREATE TABLE measurement ( city_id int not null, logdate date not null, peaktemp int, unitsales int ) DISTRIBUTED BY (city_id) PARTITION BY RANGE (logdate) (START (date '2020-01-01') INCLUSIVE END (date '2020-02-01') EXCLUSIVE EVERY (INTERVAL '1 month')); |
又例如,我们来创建一个sales表,按照date列Range分区,从2008年到2009年每月创建一个分区:
要查看创建的表信息,可以通过\d+给出该表的所有信息
|
postgres=# \d+ sales
Append-Only Table "public.sales"
Column | Type | Modifiers | Storage | Description --------+---------------+-----------+---------+-------------
id |integer | date | date | amt | numeric(10,2) | Compression Type: None Compression Level: 0 Block Size: 32768 Checksum: f Child tables: sales_1_prt_1,
sales_1_prt_10,
sales_1_prt_11,
sales_1_prt_12,
sales_1_prt_2,
sales_1_prt_3,
sales_1_prt_4,
sales_1_prt_5,
sales_1_prt_6,
sales_1_prt_7,
sales_1_prt_8,
sales_1_prt_9
Has OIDs: no Options: appendonly=true Distributed randomly Partition by: (date)
|plain | | plain | | main | |
你也可以显式得声明子分区并指定子表名字。
|
CREATE TABLE sales_exp (id int, date date, amt decimal(10,2)) PARTITION BY RANGE (date) ( PARTITION Jan08 START (date '2008-01-01') INCLUSIVE , PARTITION Feb08 START (date '2008-02-01') INCLUSIVE , PARTITION Mar08 START (date '2008-03-01') INCLUSIVE , PARTITION Apr08 START (date '2008-04-01') INCLUSIVE , PARTITION May08 START (date '2008-05-01') INCLUSIVE , PARTITION Jun08 START (date '2008-06-01') INCLUSIVE , PARTITION Jul08 START (date '2008-07-01') INCLUSIVE , PARTITION Aug08 START (date '2008-08-01') INCLUSIVE , PARTITION Sep08 START (date '2008-09-01') INCLUSIVE , PARTITION Oct08 START (date '2008-10-01') INCLUSIVE , PARTITION Nov08 START (date '2008-11-01') INCLUSIVE , PARTITION Dec08 START (date '2008-12-01') INCLUSIVE
END (date '2009-01-01') EXCLUSIVE ); |
查看创建的表信息
postgres=# CREATE TABLE sales (id int, date date, amt decimal(10,2))
PARTITION BY RANGE (date)
( START (date '2008-01-01') INCLUSIVE
END (date '2009-01-01') EXCLUSIVE EVERY (INTERVAL '1 month') );
下面是另外一个根据Range分区的例子,这次使用的是整型列进行分区。这里面我们添加了一个 DEFAULT PARTITION, 在不满足其他分区的条件下,数据会被插入DEFAULT PARTITION。
定义List分区
列表分区的分区字段可以是任意可进行等于比较的数据类型,且允许多列组合进行分区,而范围分区只 允许选定一列作分区字段。列表分区时必须显式为每个分区申明分区值,比如还是上述提到的冰淇淋数 据表,我们可以按照地区列表对数据进行分区操作:
|
CREATE TABLE rank (id int, rank int, year int, gender char(1), count int)
PARTITION BY RANGE (year)
( START (2001) END (2008) EVERY (1),
DEFAULT PARTITION extra );
|




