数据分布
====

从数据分布的角度看，OceanBase 数据库是数据库分区表在分布式系统的实现，语法和使用兼容传统的数据库分区表。当表格的容量或者服务能力不足时，只需要通过 OceanBase 管理命令增加更多表格分区即可。

分布式分区表 
---------------

传统数据库支持分区表，常见的分区方式包括 Hash 分区、Range 分区、List 分区，且支持二级组合分区。OceanBase 数据库沿用了分区表的使用方式，但是分区可以均匀分布在数据库任意节点上。OceanBase 数据库以分布式分区表数据模型为基础，一方面，数据存储和处理能力能够水平扩展，享受分布式技术的红利，另一方面，使用者不感知后端的分布式架构，可以像使用单机数据库一样使用分布式数据库，具有完整的全局索引和全局约束。

分区类型 
-------------

OceanBase 数据库支持多种分区策略，可以将数据按照符合应用需要的方式分成多个分区，支持的分区方式有 Hash、Range、List 三种分区方式。OceanBase 数据库还支持一级分区和二级分区两种分区模式。一级分区允许分区表以某种分区策略设置一组分区键，数据按照一个维度进行划分。二级分区是一种组合分区方式，在一级分区的基础上，每一个一级分区还可以再选择一种分区策略和另一组分区键，将数据再次进行划分。

OceanBase 数据库对分区键的选择有要求，如果表格设置了 Primary Keys，那么分区键必须是 Primary Keys 中的列，如果表格没有设置 Primary Keys，那么分区键没有要求。

**Hash 分区**

Hash 分区需要指定分区键和分区个数。通过 Hash 的分区表达式计算得到一个 int 类型的结果，这个结果再和分区个数取模得到具体这行数据属于哪个分区。通常用于给定分区键的点查询，例如按照用户 ID 来分区。Hash 分区通常能消除热点查询。

下面的例子创建了 t1 表，选择 c1 列作为分区键进行 Hash 分区，分区个数是 5 个。

```javascript
create table t1  (c1 int, c2 int) partition by hash(c1) partitions 5
```

**Range 分区**

Range 分区是按照分区表达式的范围来划分分区。通常用于对分区键需要按照范围的查询。例如通过按照时间字段进行范围分区，还有价格区间等一些分区方式。

下面的例子创建了 t2 表，选择 c1 列作为分区键进行 Range 分区，分成 3 个分区 p0、p1、p2，分区范围分别是 (min, 100), \[100, 500), \[500, max)。

```javascript
CREATE TABLE t2  (c1 NUMBER, c2 NUMBER) PARTITION BY RANGE(c1) (
PARTITION p0 VALUES LESS THAN(100), 
PARTITION p1 VALUES LESS THAN(500), 
PARTITION p2 VALUES LESS THAN(MAXVALUE)
);
```

**List 分区**

List 分区是根据枚举类型的值来划分分区的。主要用于枚举类型。

下面的例子创建了 t3 表，选择 c1 列作为分区键进行 List 分区，当某一行的 c1 = 1 or c1 = 2 or c1 = 3 的时候，那么这一行属于分区 p0，当 c1 = 5 or c1 = 6 的时候，那么这一行属于分区 p1。除此之外都所有行都属于 p2。

```javascript
CREATE TABLE t3  (c1 NUMBER, c2 NUMBER) PARTITION BY RANGE(c1) (
PARTITION p0 VALUES IN (1,2,3), 
PARTITION p1 VALUES IN (5, 6), 
PARTITION p2 VALUES IN (DEFAULT)
);
```

**二级分区**

按照两个维度来把数据拆分成分区。

最常用的地方就是类似用户账单领域，会按照 user_id 做 hash 分区，按照账单创建时间做 range 分区。所有二级分区的组合方式有 hash + hash, hash + range, hash + list, range + hash, range + range, range + list, list + hash, list + range, list + list。

