OceanBase 支持多种分区策略:

  • 范围(RANGE)分区
  • RANGE COLUMNS 分区
  • 列表(LIST)分区
  • LIST COLUMNS 分区
  • 哈希(HASH)分区
  • 组合分区

范围(RANGE)分区

RANGE 分区根据分区表定义时为每个分区建立的分区键值范围,将数据映射到相应的分区中。它是常见的分区类型,经常跟日期类型一起使用。比如说,可以将业务日志表按日/周/月分区。RANGE 分区简单的语法格式如下:

  1. CREATE TABLE table_name (
  2. column_name1 column_type
  3. [, column_nameN column_type]
  4. ) PARTITION BY RANGE ( expr(column_name1) )
  5. (
  6. PARTITION p0 VALUES LESS THAN ( expr )
  7. [, PARTITION pN VALUES LESS THAN (expr ) ]
  8. [, PARTITION pX VALUES LESS THAN (maxvalue) ]
  9. );

当使用RANGE分区时,需要遵守如下几个规则:

  • PARTITION BY RANGE ( expr ) 里的 expr 表达式的结果必须为整形。
  • 每个分区都有一个 VALUES LESS THAN 子句,它为分区指定一个非包含的上限值。分区键的任何值等于或大于这个值时将被映射到下一个分区中。
  • 除第一个分区外,所有分区都隐含一个下限值,即上一个分区的上限值。
  • 允许且只允许最后一个分区上限定义为 MAXVALUE ,这个值没有具体的数值,比其他所有分区的上限都要大,也包含空值。

示例:创建一个 RANGE 分区表。

  1. CREATE TABLE t_log_part_by_range (
  2. log_id bigint NOT NULL
  3. , log_value varchar(50)
  4. , log_date timestamp NOT NULL
  5. ) PARTITION BY RANGE(UNIX_TIMESTAMP(log_date))
  6. (
  7. PARTITION M202001 VALUES LESS THAN(UNIX_TIMESTAMP('2020/02/01'))
  8. , PARTITION M202002 VALUES LESS THAN(UNIX_TIMESTAMP('2020/03/01'))
  9. , PARTITION M202003 VALUES LESS THAN(UNIX_TIMESTAMP('2020/04/01'))
  10. , PARTITION M202004 VALUES LESS THAN(UNIX_TIMESTAMP('2020/05/01'))
  11. , PARTITION M202005 VALUES LESS THAN(UNIX_TIMESTAMP('2020/06/01'))
  12. , PARTITION M202006 VALUES LESS THAN(UNIX_TIMESTAMP('2020/07/01'))
  13. , PARTITION M202007 VALUES LESS THAN(UNIX_TIMESTAMP('2020/08/01'))
  14. , PARTITION M202008 VALUES LESS THAN(UNIX_TIMESTAMP('2020/09/01'))
  15. , PARTITION M202009 VALUES LESS THAN(UNIX_TIMESTAMP('2020/10/01'))
  16. , PARTITION M202010 VALUES LESS THAN(UNIX_TIMESTAMP('2020/11/01'))
  17. , PARTITION M202011 VALUES LESS THAN(UNIX_TIMESTAMP('2020/12/01'))
  18. , PARTITION M202012 VALUES LESS THAN(UNIX_TIMESTAMP('2021/01/01'))
  19. );

RANGE 分区可以新增、删除分区。如果最后一个 RANGE 分区指定了 MAXVALUE ,则不能新增分区。

RANGE 分区要求表拆分键表达式的结果必须为整型,如果要按时间类型列做 RANGE 分区,则必须使用 timestamp 类型,并且使用函数 UNIX_TIMESTAMP 将时间类型转换为数值。这个需求也可以使用 RANGE COLUMNS 分区实现,就没有整型这个要求。

RANGE COLUMNS分区

RANGE COLUMNS 分区作用跟 RANGE 分区基本类似,不同之处在于:

  • range columns 拆分列结果不要求是整型,可以是任意类型。
  • range columns 拆分列不能使用表达式。
  • range columns 拆分列可以写多个列(即列向量)。

RANGE COLUMNS分区的简单语法格式如下:

  1. CREATE TABLE table_name (
  2. column_name1 column_type
  3. [, column_nameN column_type]
  4. ) PARTITION BY RANGE ( column_name1 [, column_name2] )
  5. (
  6. PARTITION p0 VALUES LESS THAN ( expr )
  7. [, PARTITION pN VALUES LESS THAN (expr ) ]
  8. [, PARTITION pX VALUES LESS THAN (maxvalue) ]
  9. );

示例:创建一个 RANGE COLUMNS 分区

  1. CREATE TABLE t_log_part_by_range_columns (
  2. log_id bigint NOT NULL
  3. , log_value varchar(50)
  4. , log_date date NOT NULL
  5. ) PARTITION BY RANGE COLUMNS(log_date)
  6. (
  7. PARTITION M202001 VALUES LESS THAN('2020/02/01')
  8. , PARTITION M202002 VALUES LESS THAN('2020/03/01')
  9. , PARTITION M202003 VALUES LESS THAN('2020/04/01')
  10. , PARTITION M202004 VALUES LESS THAN('2020/05/01')
  11. , PARTITION M202005 VALUES LESS THAN('2020/06/01')
  12. , PARTITION M202006 VALUES LESS THAN('2020/07/01')
  13. , PARTITION M202007 VALUES LESS THAN('2020/08/01')
  14. , PARTITION M202008 VALUES LESS THAN('2020/09/01')
  15. , PARTITION M202009 VALUES LESS THAN('2020/10/01')
  16. , PARTITION M202010 VALUES LESS THAN('2020/11/01')
  17. , PARTITION M202011 VALUES LESS THAN('2020/12/01')
  18. , PARTITION M202012 VALUES LESS THAN('2021/01/01')
  19. , PARTITION MMAX VALUES LESS THAN MAXVALUE
  20. );

列表(LIST)分区

LIST 分区使得您可以显式的控制记录行如何映射到分区,具体方法是为每个分区的分区键指定一组离散值列表,这点跟 RANGE 分区和 HASH 分区都不同。LIST 分区的优点是可以方便的对无序或无关的数据集进行分区。LIST 分区的简单语法格式如下:

  1. CREATE TABLE table_name (
  2. column_name1 column_type
  3. [, column_nameN column_type]
  4. ) PARTITION BY LIST ( expr(column_name1) )
  5. (
  6. PARTITION p0 VALUES IN ( v01 [, v0N] )
  7. [, PARTITION pN VALUES IN ( vN1 [, vNN] ) ]
  8. [, PARTITION pX VALUES IN (default) ]
  9. );

当使用列表分区时,需要遵守以下规则:

  • 分区表达式结果必须是整型。
  • 分区表达式只能引用一列,不能有多列(即列向量)。

示例:创建一个 LIST 分区表。

  1. CREATE TABLE t_part_by_list (
  2. c1 BIGINT PRIMARY KEY
  3. , c2 VARCHAR(50)
  4. ) PARTITION BY list(c1)
  5. (
  6. PARTITION p0 VALUES IN (1, 2, 3)
  7. , PARTITION p1 VALUES IN (5, 6)
  8. , PARTITION p2 VALUES IN (DEFAULT)
  9. );

LIST 分区可以新增分区,指定新的不重复的列表。也可以删除分区。

LIST COLUMNS 分区

LIST COLUMNS 分区作用跟 LIST 分区基本相同,不同之处在于:

  • LIST COLUMNS 的拆分列不能是表达式。
  • LIST COLUMNS 的拆分列可以是多列(即列向量)。

LIST COLUMNS 分区简单的语法格式如下:

  1. CREATE TABLE table_name (
  2. column_name1 column_type
  3. [, column_nameN column_type]
  4. ) PARTITION BY LIST COLUMNS ( column_name1 [, column_nameN ] )
  5. (
  6. PARTITION p0 VALUES IN ( v01 [, v0N] )
  7. [, PARTITION pN VALUES IN ( vN1 [, vNN] ) ]
  8. [, PARTITION pX VALUES IN (default) ]
  9. );

示例:创建一个 LIST COLUMNS 分区

  1. CREATE TABLE t2 (
  2. id varchar(64),
  3. type varchar(16),
  4. info varchar(512),
  5. gmt_create datetime(6),
  6. gmt_modified datetime(6),
  7. partition_id varchar(2) GENERATED ALWAYS AS (substr(`id`,19,20)) VIRTUAL,
  8. PRIMARY KEY (id),
  9. )partition by list columns(partition_id)
  10. (partition p0 values in ('00','01'),
  11. partition p1 values in ('02','03'),
  12. partition p2 values in (default));

哈希(HASH)分区

HASH 分区适合于对不能用RANGE分区、LIST分区方法的场景,它的实现方法简单,通过对分区键上的 HASH 函数值来散列记录到不同分区中。如果您的数据符合下列特点,使用HASH分区是个很好的选择:

  • 不能指定数据的分区键的列表特征。
  • 不同范围内的数据大小相差非常大,并且很难手动调整均衡。
  • 使用 RANGE 分区后数据聚集严重。
  • 并行DML、分区剪枝和分区连接等性能非常重要。

示例:创建一个 HASH 分区表。

  1. CREATE TABLE ware(
  2. w_id number
  3. , w_ytd number(12,2)
  4. , w_tax number(4,4)
  5. , w_name varchar(10)
  6. , w_street_1 varchar(20)
  7. , w_street_2 varchar(20)
  8. , w_city varchar(20)
  9. , w_state char(2)
  10. , w_zip char(9)
  11. , primary key(w_id)
  12. )tablegroup tpcc_group
  13. PARTITION by hash(w_id) partitions 60;

HASH 分区不适合做删除操作。

组合分区

组合分区通常是先使用一种分区策略,然后在子分区再使用另外一种分区策略,适合于业务表的数据量非常大时。使用组合分区能发挥多种分区策略的优点。

在指定二级分区分区策略细节时,可以使用 SUBPARTITION TEMPLATE 子句。OceanBase 目前不支持两个一级分区下使用不同定义的二级分区。

示例:创建组合分区表。

  1. CREATE TABLE t_ordr_part_by_hash_range (o_w_id int
  2. , o_d_id int,
  3. , o_id int
  4. , o_c_id int
  5. , o_carrier_id int
  6. , o_ol_cnt int
  7. , o_all_local int
  8. , o_entry_d date
  9. , index idx_ordr(o_w_id, o_d_id, o_c_id, o_id) LOCAL
  10. , primary key ( o_w_id, o_d_id, o_id, o_entry_d )
  11. )
  12. PARTITION BY hash(o_w_id)
  13. SUBPARTITION BY RANGE(o_entry_d)
  14. SUBPARTITION template
  15. (
  16. SUBPARTITION M202001 VALUES LESS THAN(TO_DATE('2020/02/01','YYYY/MM/DD'))
  17. , SUBPARTITION M202002 VALUES LESS THAN(TO_DATE('2020/03/01','YYYY/MM/DD'))
  18. , SUBPARTITION M202003 VALUES LESS THAN(TO_DATE('2020/04/01','YYYY/MM/DD'))
  19. , SUBPARTITION M202004 VALUES LESS THAN(TO_DATE('2020/05/01','YYYY/MM/DD'))
  20. , SUBPARTITION M202005 VALUES LESS THAN(TO_DATE('2020/06/01','YYYY/MM/DD'))
  21. , SUBPARTITION M202006 VALUES LESS THAN(TO_DATE('2020/07/01','YYYY/MM/DD'))
  22. , SUBPARTITION M202007 VALUES LESS THAN(TO_DATE('2020/08/01','YYYY/MM/DD'))
  23. , SUBPARTITION M202008 VALUES LESS THAN(TO_DATE('2020/09/01','YYYY/MM/DD'))
  24. , SUBPARTITION M202009 VALUES LESS THAN(TO_DATE('2020/10/01','YYYY/MM/DD'))
  25. , SUBPARTITION M202010 VALUES LESS THAN(TO_DATE('2020/11/01','YYYY/MM/DD'))
  26. , SUBPARTITION M202011 VALUES LESS THAN(TO_DATE('2020/12/01','YYYY/MM/DD'))
  27. , SUBPARTITION M202012 VALUES LESS THAN(TO_DATE('2021/01/01','YYYY/MM/DD'))
  28. , SUBPARTITION MMAX VALUES LESS THAN MAXVALUE
  29. )
  30. partitions 16;
  31. CREATE TABLE t_log_part_by_range_hash (
  32. log_id number NOT NULL
  33. , log_value varchar2(50)
  34. , log_date date NOT NULL DEFAULT sysdate
  35. , PRIMARY key(log_id, log_date)
  36. ) PARTITION BY RANGE(log_date)
  37. SUBPARTITION BY HASH(log_id) SUBPARTITIONS 16
  38. (
  39. PARTITION M202001 VALUES LESS THAN(TO_DATE('2020/02/01','YYYY/MM/DD'))
  40. , PARTITION M202002 VALUES LESS THAN(TO_DATE('2020/03/01','YYYY/MM/DD'))
  41. , PARTITION M202003 VALUES LESS THAN(TO_DATE('2020/04/01','YYYY/MM/DD'))
  42. , PARTITION M202004 VALUES LESS THAN(TO_DATE('2020/05/01','YYYY/MM/DD'))
  43. , PARTITION M202005 VALUES LESS THAN(TO_DATE('2020/06/01','YYYY/MM/DD'))
  44. , PARTITION M202006 VALUES LESS THAN(TO_DATE('2020/07/01','YYYY/MM/DD'))
  45. , PARTITION M202007 VALUES LESS THAN(TO_DATE('2020/08/01','YYYY/MM/DD'))
  46. , PARTITION M202008 VALUES LESS THAN(TO_DATE('2020/09/01','YYYY/MM/DD'))
  47. , PARTITION M202009 VALUES LESS THAN(TO_DATE('2020/10/01','YYYY/MM/DD'))
  48. , PARTITION M202010 VALUES LESS THAN(TO_DATE('2020/11/01','YYYY/MM/DD'))
  49. , PARTITION M202011 VALUES LESS THAN(TO_DATE('2020/12/01','YYYY/MM/DD'))
  50. , PARTITION M202012 VALUES LESS THAN(TO_DATE('2021/01/01','YYYY/MM/DD'))
  51. , PARTITION MMAX VALUES LESS THAN MAXVALUE
  52. );

由于 OceanBase 里二级分区必须使用 SUBPARTITION TEMPLATE ,如果二级分区是 RANGE 则不支持对二级分区进行 ADD/DROP 操作,所以通常建议使用 RANGE-HASH 这种组合分区方式而不是 HASH-RANGE 组合分区。