Move the docs folder

This commit is contained in:
LINxiansheng
2022-02-10 14:51:49 +08:00
committed by LINxiansheng
parent 7c6dcc6712
commit d42f317422
1160 changed files with 0 additions and 3 deletions

View File

@ -0,0 +1,46 @@
关于 DDL 语句
==============================
DDL(Data Definition Language,数据定义语言)语句用来创建、修改和删除数据库对象。在 DDL 开始之前和之后,OceanBase 数据库会发出一个隐式的 COMMIT 语句,所以不可以回滚 DDL 语句。
**说明**
在 obclient 命令行环境下,可以在"SQL提示符\>"后输入 DDL 语句。
在 ODC 的 SQL 编辑器窗口,也可以输入 DDL 语句。
OceanBase DDL 支持的数据库对象有:
* 表,包括约束、索引
表是最基础的数据存储单元。表包含所有用户可以访问的数据,每个表包含多行记录,每个记录由多个列组成。
<!-- -->
* 视图
视图表示表的查询结果。大部分能使用表的地方,都可以使用视图。如果经常访问的数据分布在多个表里时,使用视图是最好的方法。
<!-- -->
* 自定义函数
* 自定义类型

View File

@ -0,0 +1,36 @@
关于 SQL 数据类型
================================
当您创建表的时候,必须指定表记录行的每一列的数据类型,数据类型定义了该列存储数据的合法格式。比如说一个 DATE 类型的列,能存储值"2020-02-20",但是不能存储值为 2 的数字或者字符串"hello"。
有关 SQL 数据类型的详细描述,请参考《SQL参考(MySQL模式)》,这里介绍一些常用的数据类型。
| **分类** | **类型** | **备注** |
|----------------|---------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 数值类型-整形 | bigint | 有符号:\[-2\^63, 2\^63 - 1\] 无符号:\[0, 2\^64 - 1\] |
| 数值类型-整形 | int integer | 有符号:\[-2\^31, 2\^31-1\] 无符号:\[0, 2\^32-1\] |
| 数值类型-整形 | smallint | 有符号:\[-2\^15, 2\^15-1\] 无符号:\[0, 2\^16-1\] |
| 数值类型-整形 | bool boolean tinyint | 有符号:\[-2\^7, 2\^7-1\] 无符号:\[0, 2\^8-1\] |
| 数值类型-定点 | decimal(p, s) | decimal 等同于 numeric |
| 数值类型-浮点 | float | 有符号:\[-2\^128, 2\^128\] 无符号:\[-2\^1024, 2\^1024\] 精度7位 |
| 数值类型-浮点 | double | 有符号:\[-2\^1024, 2\^1024\] 无符号:\[0, 2\^1024\] 精度15位 |
| 数值类型- 整形/定点/浮点 | number number(p) number(p, s) | p(precision) 为精度,s(scale) 表示小数点右边的数字个数,精度最大值为 38,scale 的取值范围为 -84 到 127。 * p 和 s 都有表示定点数。 * s 为 0 表示整形。 * p 和 s 都不指定,表示浮点数,最大精度 38。 |
| 字符类型-变长 | varchar(N) | 最长 256K,字符集 UTF8MB4 |
| 字符类型-变长 | varbinary | 最初 256K,字符集 BINARY |
| 字符类型-变长 | enum | 最多 65535 个元素,每个元素最长 255 个字符,字符集 UTF8MB4 |
| 字符类型-变长 | set | 最多 64 个元素,每个元素最长255 个字符,字符集 UTF8MB4 |
| 字符类型-定长 | char(N) | 最大 256,字符集 UTF8MB4 |
| 字符类型-定长 | binary | 最大 256,字符集 BINARY |
| 时间类型 | date | YYYY-MM-DD,只包含日期 |
| 时间类型 | time | HH:MM:SS\[.fraction\],只包含时间。 |
| 时间类型 | datetime | YYYY-MM-DD HH:MM:SS\[.fraction\],包含日期时间(不考虑时区)。 |
| 时间类型 | Timestamp | 日期时间(考虑时区)。 |
| 时间类型 | year | YYYY,\[1901, 2155\] |
| 大对象 | Text / blob | 最大 64K |
| 大对象 | Longtext /longblob | 最大 48M |

View File

@ -0,0 +1,265 @@
创建表
========================
可以通过执行 DDL 语句 CREATE TABLE 来创建一个表。
使用 CREATE TABLE 语句建表
-----------------------------
* 下面示例使用 CREATE TABLE 语句创建订单表 ware 和 cust 表。
```javascript
obclient> create table ware(w_id int
, w_ytd decimal(12,2)
, w_tax decimal(4,4)
, w_name varchar(10)
, w_street_1 varchar(20)
, w_street_2 varchar(20)
, w_city varchar(20)
, w_state char(2)
, w_zip char(9)
, unique(w_name, w_city)
, primary key(w_id)
);
Query OK, 0 rows affected (0.06 sec)
obclient> create table cust (c_w_id int NOT NULL
, c_d_id int NOT null
, c_id int NOT null
, c_discount decimal(4, 4)
, c_credit char(2)
, c_last varchar(16)
, c_first varchar(16)
, c_middle char(2)
, c_balance decimal(12, 2)
, c_ytd_payment decimal(12, 2)
, c_payment_cnt int
, c_credit_lim decimal(12, 2)
, c_street_1 varchar(20)
, c_street_2 varchar(20)
, c_city varchar(20)
, c_state char(2)
, c_zip char(9)
, c_phone char(16)
, c_since date
, c_delivery_cnt int
, c_data varchar(500)
, index icust(c_last, c_d_id, c_w_id, c_first, c_id)
, FOREIGN KEY (c_w_id) REFERENCES ware(w_id)
, primary key (c_w_id, c_d_id, c_id)
);
Query OK, 0 rows affected (0.06 sec)
```
**说明**
由于 ALTER TABLE 语法不支持后期增加主键,所以需要在建表的时候设置主键。
使用 CREATE TABLE 复制表数据
------------------------------
在 MySQL 租户里,可以使用 CREATE TABLE AS SELECT 复制表的数据,但是结构并不完全一致,会丢失约束、索引、默认值、分区等信息。使用 CREATE TABLE LIKE 可以复制表结构,但是不包括数据。
* 示例:MySQL 租户的 CREATE TABLE 复制表结构和数据的区别
```javascript
obclient> create table t1(
id bigint not null primary KEY
, name varchar(50) not NULL
, gmt_create timestamp not null default current_timestamp
) partition by hash(id) partitions 8;
Query OK, 0 rows affected (0.10 sec)
obclient> insert into t1(id,name) values(1,'A'),(2,'B'),(3,'C');
Query OK, 3 rows affected (0.03 sec)
Records: 3 Duplicates: 0 Warnings: 0
obclient> create table t1_like like t1;
Query OK, 0 rows affected (0.11 sec)
obclient> create table t1_copy as select * from t1;
Query OK, 3 rows affected (0.12 sec)
obclient> show create table t1_like\G
*************************** 1. row ***************************
Table: t1_like
Create Table: CREATE TABLE `t1_like` (
`id` bigint(20) NOT NULL,
`name` varchar(50) NOT NULL,
`gmt_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.0' REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 10 PROGRESSIVE_MERGE_NUM = 2
partition by hash(id)
(partition p0,
partition p1,
partition p2,
partition p3,
partition p4,
partition p5,
partition p6,
partition p7)
1 row in set (0.02 sec)
obclient> show create table t1_copy\G
*************************** 1. row ***************************
Table: t1_copy
Create Table: CREATE TABLE `t1_copy` (
`id` bigint(20) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
`gmt_create` timestamp NULL DEFAULT NULL
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.0' REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 10
1 row in set (0.00 sec)
obclient> show create table t1\G
*************************** 1. row ***************************
Table: t1
Create Table: CREATE TABLE `t1` (
`id` bigint(20) NOT NULL,
`name` varchar(50) NOT NULL,
`gmt_create` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) DEFAULT CHARSET = utf8mb4 ROW_FORMAT = DYNAMIC COMPRESSION = 'zstd_1.0' REPLICA_NUM = 3 BLOCK_SIZE = 16384 USE_BLOOM_FILTER = FALSE TABLET_SIZE = 134217728 PCTFREE = 10 PROGRESSIVE_MERGE_NUM = 2
partition by hash(id)
(partition p0,
partition p1,
partition p2,
partition p3,
partition p4,
partition p5,
partition p6,
partition p7)
1 row in set (0.01 sec)
```
关于表和分区
---------------
在 OceanBase 数据库中,数据存储在表中,而数据表示的最小粒度是分区。普通的非分区表,就只有一个分区;而分区表,通常有多个分区,分区名默认以 p 开头,按数字顺序从 0 开始编号。所以分区是表的子集。
通常分区对用户的应用是透明的,应用只需要使用 SQL 读写表即可。只有某些场景下,为了提升分区表的查询性能,应用也可以使用 SQL 直接访问某个具体的分区,SQL 语法格式是:
```javascript
SELECT ... FROM parted_table PARTITION (pN) WHERE query_condition ;
```
* 示例:通过 SQL 直接访问分区表的分区
```javascript
obclient> select o_id,o_c_id,o_carrier_id,o_ol_cnt,o_all_local,o_entry_d from ordr partition (p1) where o_w_id=1 and o_d_id=2 and o_id=2100;
+------+--------+--------------+----------+-------------+------------+
| o_id | o_c_id | o_carrier_id | o_ol_cnt | o_all_local | o_entry_d |
+------+--------+--------------+----------+-------------+------------+
| 2100 | 8 | 8 | 11 | 1 | 2020-02-15 |
+------+--------+--------------+----------+-------------+------------+
1 row in set (0.01 sec)
obclient> select ol_o_id, ol_number,ol_delivery_d,ol_amount,ol_i_id,ol_supply_w_id,ol_quantity from ordl partition (p1) where ol_w_id=1 and ol_d_id=2 and ol_o_id=2100;
+---------+-----------+---------------+-----------+---------+----------------+-------------+
| ol_o_id | ol_number | ol_delivery_d | ol_amount | ol_i_id | ol_supply_w_id | ol_quantity |
+---------+-----------+---------------+-----------+---------+----------------+-------------+
| 2100 | 1 | 2020-02-15 | 0.00 | 87133 | 1 | 5 |
| 2100 | 2 | 2020-02-15 | 0.00 | 47413 | 1 | 5 |
| 2100 | 3 | 2020-02-15 | 0.00 | 9115 | 1 | 5 |
| 2100 | 4 | 2020-02-15 | 0.00 | 42985 | 1 | 5 |
| 2100 | 5 | 2020-02-15 | 0.00 | 43621 | 1 | 5 |
| 2100 | 6 | 2020-02-15 | 0.00 | 5787 | 1 | 5 |
| 2100 | 7 | 2020-02-15 | 0.00 | 62576 | 1 | 5 |
| 2100 | 8 | 2020-02-15 | 0.00 | 91592 | 1 | 5 |
| 2100 | 9 | 2020-02-15 | 0.00 | 34452 | 1 | 5 |
| 2100 | 10 | 2020-02-15 | 0.00 | 13792 | 1 | 5 |
| 2100 | 11 | 2020-02-15 | 0.00 | 94326 | 1 | 5 |
+---------+-----------+---------------+-----------+---------+----------------+-------------+
11 rows in set (0.01 sec)
```
**说明**
如果是组合分区,可以访问更细粒度的分区,详细描述请参考"分区路由"章节。
在 OceanBase 数据库里,节点间的数据迁移的最小粒度是分区,每个分区在集群里有三个副本,内容保持同步,角色上有区分。三副本会有一个主副本(Leader 副本)和两个备副本(Follower 副本),只有主副本可以提供写服务,默认也只有主副本可以提供读服务。主副本上的事务提交时会将事务日志同步到两个备副本,三副本使用 Paxos 协议表决事务是否提交成功。有时候为了不影响主副本,可以让备副本承担部分读请求,这就是应用常用的读写分离的解决方案,这种读备称为 **弱一致性读** 。使用这种方案,应用读需要承担读延时的风险,这个延时最大允许值会通过参数(max_stale_time_for_weak_consistency)控制。
* 示例:使用 SQL Hint 实现读写分离。
弱一致读的 Hint 语法是 /\*+ read_consistency(weak) \*/ 。通常的读默认是强一致性读,就不用 Hint 了。
```javascript
obclient> select /*+ read_consistency(weak) */ o_id,o_c_id,o_carrier_id,o_ol_cnt,o_all_local,o_entry_d from ordr where o_w_id=1 and o_d_id=2 and o_id=2100;
+------+--------+--------------+----------+-------------+------------+
| o_id | o_c_id | o_carrier_id | o_ol_cnt | o_all_local | o_entry_d |
+------+--------+--------------+----------+-------------+------------+
| 2100 | 8 | 8 | 11 | 1 | 2020-02-15 |
+------+--------+--------------+----------+-------------+------------+
1 row in set (0.00 sec)
```
复制表
------------
复制表是分布式数据库 OceanBase 的高级优化手段。
通常 OceanBase 集群是三副本架构,默认每个表的每个分区在 OceanBase 中会有三个副本数据,角色上分为一个主副本(Leader 副本)和两个备副本(Follower副本),默认提供读写服务的是主副本。
复制表可以指定在租户的每台机器上都有一个备副本,并且主副本跟所有备份的数据使用全同步策略保持强同步。这样做的目的是为了让业务有些 SQL 关联查询时能在同一节点内部执行,以获取更好的性能。
复制表的语法是在 CREATE TABLE 语句后增加 `DUPLICATE_SCOPE` 选项。
* 示例:创建复制表。
```javascript
obclient> create table item (i_id int
, i_name varchar(24)
, i_price decimal(5,2)
, i_data varchar(50)
, i_im_id int
, primary key(i_id)) pctfree=0 BLOCK_SIZE=16384
duplicate_scope='cluster' locality='F@zone1,F@zone2,R{all_server}@zone3' primary_zone='zone1';
Query OK, 0 rows affected (0.06 sec)
```

View File

@ -0,0 +1,81 @@
关于自增列
==========================
如果创建表时需要某个数值列的值不重复并且保持递增,这就是自增列。在 MySQL 租户里,列的类型可以定义为 AUTO_INCREMENT,即 MySQL 租户的自增列。
自增列有三个重要属性:自增起始值、自增步长、自增列缓存大小,通过以下三个租户变量参数控制。
```javascript
obclient> show variables where variable_name in ('auto_increment_increment','auto_increment_offset','auto_increment_cache_size');
+---------------------------+---------+
| Variable_name | Value |
+---------------------------+---------+
| auto_increment_cache_size | 1000000 |
| auto_increment_increment | 1 |
| auto_increment_offset | 1 |
+---------------------------+---------+
3 rows in set (0.01 sec)
```
**示例:CREATE TABLE 使用自增列**
下面创建了一个自增列,在使用 INSERT 插入记录的时候不需要指定自增列,OceanBase 数据库会自动为该列填充值。
```javascript
obclient> create table t1(id bigint not null auto_increment primary key, name varchar(50), gmt_create timestamp not null default current_timestamp);
Query OK, 0 rows affected (0.08 sec)
obclient> insert into t1(name) values('A'),('B'),('C');
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
obclient> select * from t1;
+----+------+---------------------+
| id | name | gmt_create |
+----+------+---------------------+
| 1 | A | 2020-04-03 17:09:55 |
| 2 | B | 2020-04-03 17:09:55 |
| 3 | C | 2020-04-03 17:09:55 |
+----+------+---------------------+
3 rows in set (0.01 sec)
```
假如在 INSERT 时指定了自增列的值,如果这个值是0,则 OceanBase 数据库会用自增列的下一个值填充列的值;如果这个值比当前最大值小,则不影响自增列的下一个值的计算;如果这个值比当前值最大值大,则自增列会把插入值和自增列缓存值的和作为下次自增的起始值。
```javascript
obclient> insert into t1(id, name) values(0, 'D');
Query OK, 1 row affected (0.00 sec)
obclient> insert into t1(id, name) values(-1,'E');
Query OK, 1 row affected (0.00 sec)
obclient> insert into t1(id, name) values(10,'F');
Query OK, 1 row affected (0.01 sec)
obclient> insert into t1(name) values('G');
Query OK, 1 row affected (0.00 sec)
obclient> select * from t1;
+---------+------+---------------------+
| id | name | gmt_create |
+---------+------+---------------------+
| -1 | E | 2020-04-03 17:10:24 |
| 1 | A | 2020-04-03 17:09:55 |
| 2 | B | 2020-04-03 17:09:55 |
| 3 | C | 2020-04-03 17:09:55 |
| 4 | D | 2020-04-03 17:10:19 |
| 10 | F | 2020-04-03 17:10:29 |
| 1000011 | G | 2020-04-03 17:10:34 |
+---------+------+---------------------+
7 rows in set (0.00 sec)
```

View File

@ -0,0 +1,87 @@
关于列的约束类型
=============================
为了确保表里的数据符合业务规则,可以在列上定义约束。
约束定义在列上,限制了列里存储的值。当尝试在该列上写入或更新为违反约束定义的值时,会触发一个错误并回滚这个操作;当尝试在已有的表的列上加上一个跟现有数据相冲突的约束时,也会触发一个错误并回滚这个操作。
约束的类型有:
* 非空约束(NOT NULL),不允许约束包含的列的值包含 NULL。
如 ware 表的 w_name 列类型后面有 not null 约束,表示业务约束每个仓库必须有个名称。有非空约束的列,在 INSERT 语句中必须指明该列的值,除非该列还定义了默认值。如 cust 表的列 c_discount 定义了默认值 0.99,即业务上每个人默认折扣是 0.99。
<!-- -->
* 唯一约束(UNIQUE),不允许约束包含的列的值有重复值,但是可以有多个 NULL 值。
如 ware 表的 (w_name, w_city) 列上有个唯一约束,表示每个城市里仓库的名称必须是不重复的。
<!-- -->
* 主键约束(PRIMARY KEY),是 NOT NULL 约束和唯一约束的组合。
如 ware 表和 cust 表都有个主键 w_id 和 c_id ,这两列不允许为 NULL 并且必须是不重复的。
<!-- -->
* 外键约束(FOREIGN KEY),要求约束的列的值取自于另外一个表的主键列。
如 cust 表的 c_w_id 上有个外键约束引用了 ware 表的 w_id 列,表示业务上顾客归属的仓库必须是属于仓库表里的仓库。
OceanBase 数据库默认是开启外键约束的,通过租户变量 foreign_key_checks 控制。
关于时间列的默认时间设置
---------------------
当列上有 NOT NULL 约束时,通常建议设置默认值。当列类型是日期或时间类型时,可以设置默认值为数据库当前时间。
* 示例:为表的时间列设置默认值,可以使用 current_timestamp 函数。
```javascript
obclient> create table t1(
id bigint not null primary KEY
, gmt_create datetime not null default current_timestamp
, gmt_modified datetime not null default current_timestamp
);
Query OK, 0 rows affected (0.07 sec)
obclient> insert into t1(id) values(1),(2),(3);
Query OK, 3 rows affected (0.01 sec)
Records: 3 Duplicates: 0 Warnings: 0
obclient> select * from t1;
+----+---------------------+---------------------+
| id | gmt_create | gmt_modified |
+----+---------------------+---------------------+
| 1 | 2020-02-27 17:09:23 | 2020-02-27 17:09:23 |
| 2 | 2020-02-27 17:09:23 | 2020-02-27 17:09:23 |
| 3 | 2020-02-27 17:09:23 | 2020-02-27 17:09:23 |
+----+---------------------+---------------------+
3 rows in set (0.00 sec)
```

View File

@ -0,0 +1,128 @@
关于表的索引
===========================
可以在表的一个或多个列上创建索引以加速表上的 SQL 语句执行速度。索引使用正确的话,可以减少物理 IO 或者逻辑 IO。
如果创建表时同时设置了主键,OceanBase 数据库会默认创建一个唯一索引。以下面的 SQL 为例:
```javascript
obclient> DROP TABLE IF EXISTS t1;
Query OK, 0 rows affected (0.01 sec)
obclient> CREATE TABLE t1(id bigint not null primary key, name varchar(50));
Query OK, 0 rows affected (0.05 sec)
obclient> show indexes from t1\G
*************************** 1. row ***************************
Table: t1
Non_unique: 0
Key_name: PRIMARY
Seq_in_index: 1
Column_name: id
Collation: A
Cardinality: NULL
Sub_part: NULL
Packed: NULL
Null:
Index_type: BTREE
Comment: available
Index_comment:
Visible: YES
1 row in set (0.01 sec)
```
新增索引
-------------
为表增加索引可以通过 CREATE INDEX 语句。OceanBase 能在普通表和分区表上创建索引,索引可以是本地索引或者全局索引。同时索引可以是唯一索引或者普通索引,如果是分区表的唯一索引,唯一索引必须包含表分区的拆分键。
创建索引的 SQL 语法格式如下:
```javascript
CREATE [UNIQUE] INDEX index_name ON table_name ( column_list ) [LOCAL | GLOBAL] [ PARTITION BY column_list PARTITIONS N ] ;
```
MySQL 租户里,索引名称在表范围内不能重复,查看索引可以通过命令 SHOW INDEXES 。
在 MySQL 租户里,新增索引还有一种方法,SQL 语法格式如下:
```javascript
ALTER TABLE table_name
ADD|DROP INDEX|KEY index_name ( column_list ) ;
```
可以一次增加多个索引,索引关键字用 INDEX 或 KEY 都可以。
* 示例:对分区表新增索引
```javascript
obclient> create table t3(
id bigint not null primary KEY
, name varchar(50)
, gmt_create timestamp not null default current_timestamp
) partition by hash(id) partitions 8;
Query OK, 0 rows affected (0.14 sec)
obclient> alter table t3 add unique key t3_uk (name) local;
ERROR 1503 (HY000): A UNIQUE INDEX must include all columns in the table's partitioning function
obclient> alter table t3
add unique key t3_uk (name, id) LOCAL
, add key t3_ind3(gmt_create) global;
Query OK, 0 rows affected (18.03 sec)
obclient> show indexes from t3;
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
| t3 | 0 | PRIMARY | 1 | id | A | NULL | NULL | NULL | | BTREE | available | | YES |
| t3 | 0 | t3_uk | 1 | name | A | NULL | NULL | NULL | YES | BTREE | available | | YES |
| t3 | 0 | t3_uk | 2 | id | A | NULL | NULL | NULL | | BTREE | available | | YES |
| t3 | 1 | t3_ind3 | 1 | gmt_create | A | NULL | NULL | NULL | | BTREE | available | | YES |
+-------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
4 rows in set (0.01 sec)
```
删除索引
-------------
删除索引的语法格式如下:
```javascript
ALTER TABLE table_name DROP key|index index_name ;
```
* 示例:删除表的索引
```javascript
obclient> alter table t3 drop key t3_uk, drop key t3_ind3;
Query OK, 0 rows affected (0.07 sec)
```

View File

@ -0,0 +1,70 @@
闪回被删除的表
============================
OceanBase 支持回收站功能,通过回收站可以闪回已删除的表。默认回收站是开启的,回收站是否开启由租户变量 recyclebin 控制。
开启/关闭回收站的语法是:
```javascript
set global recyclebin = ON | OFF ;
```
修改回收站的开启状态后,只对后续新连接会话生效。
* 示例:闪回被删除的表。
```javascript
obclient> drop table if exists t1;
Query OK, 0 rows affected (0.02 sec)
obclient> create table t1(id bigint not null primary key, gmt_create datetime not null default current_timestamp);
Query OK, 0 rows affected (0.09 sec)
obclient> insert into t1(id) values(1),(2),(3);
Query OK, 3 rows affected (0.02 sec)
Records: 3 Duplicates: 0 Warnings: 0
obclient> select * from t1;
+----+---------------------+
| ID | GMT_CREATE |
+----+---------------------+
| 1 | 2020-02-28 09:47:07 |
| 2 | 2020-02-28 09:47:07 |
| 3 | 2020-02-28 09:47:07 |
+----+---------------------+
3 rows in set (0.00 sec)
obclient> drop table t1;
Query OK, 0 rows affected (0.03 sec)
obclient> show recyclebin\G
*************************** 1. row ***************************
OBJECT_NAME: __recycle_$_20200102_1585650066255592
ORIGINAL_NAME: t1
TYPE: TABLE
CREATETIME: 2020-03-31 18:21:06.255716
1 row in set (0.03 sec)
obclient> flashback table __recycle_$_20200102_1585650066255592 to before drop rename to t1;
Query OK, 0 rows affected (0.02 sec)
obclient> select * from t1;
+----+---------------------+
| ID | GMT_CREATE |
+----+---------------------+
| 1 | 2020-02-28 09:47:07 |
| 2 | 2020-02-28 09:47:07 |
| 3 | 2020-02-28 09:47:07 |
+----+---------------------+
```

View File

@ -0,0 +1,6 @@
概述
=======================
分区技术(Partitioning)是 OceanBase 非常重要的分布式能力之一,它能解决大表的容量问题和高并发访问时性能问题,主要思想就是将大表拆分为更多更小的结构相同的独立对象,即分区。普通的表只有一个分区,可以看作分区表的特例。每个分区只能存在于一个节点内部,分区表的不同分区可以分散在不同节点上。

View File

@ -0,0 +1,34 @@
分区路由
=========================
OceanBase 的分区表是内建功能,您只需要在建表的时候指定分区策略和分区数即可。分区表的查询 SQL 跟普通表是一样的,OceanBase 的 OBProxy 或 OBServer 会自动将用户 SQL 路由到相应节点内,因此,分区表的分区细节对业务是透明的。
如果知道要读取的数据所在的分区号,可以通过 SQL 直接访问分区表的某个分区。简单语法格式如下:
```javascript
part_table partition ( p[0,1,...][sp[0,1,...]] )
```
默认情况下,除非表定义了分区名,分区名都是按一定规则编号,例如:
* 一级分区名为:p0 , p1 , p2 , ...
* 二级分区名为:p0sp0 , p0sp1 , p0sp2 , ... ; p1sp0 , p1sp1 , p1sp2 , ...
示例:访问分区表的具体分区。
```javascript
select * from t_log partition (p0) ;
select * from t_log partition (p5sp0) ;
```

View File

@ -0,0 +1,380 @@
分区策略
=========================
OceanBase 支持多种分区策略:
* 范围(RANGE)分区
* RANGE COLUMNS 分区
* 列表(LIST)分区
* LIST COLUMNS 分区
* 哈希(HASH)分区
* 组合分区
范围(RANGE)分区
--------------------
RANGE 分区根据分区表定义时为每个分区建立的分区键值范围,将数据映射到相应的分区中。它是常见的分区类型,经常跟日期类型一起使用。比如说,可以将业务日志表按日/周/月分区。RANGE 分区简单的语法格式如下:
```javascript
CREATE TABLE table_name (
column_name1 column_type
[, column_nameN column_type]
) PARTITION BY RANGE ( expr(column_name1) )
(
PARTITION p0 VALUES LESS THAN ( expr )
[, PARTITION pN VALUES LESS THAN (expr ) ]
[, PARTITION pX VALUES LESS THAN (maxvalue) ]
);
```
当使用 RANGE 分区时,需要遵守如下几个规则:
* PARTITION BY RANGE ( expr ) 里的 expr 表达式的结果必须为整形。
* 每个分区都有一个 VALUES LESS THAN 子句,它为分区指定一个非包含的上限值。分区键的任何值等于或大于这个值时将被映射到下一个分区中。
* 除第一个分区外,所有分区都隐含一个下限值,即上一个分区的上限值。
* 允许且只允许最后一个分区上限定义为 MAXVALUE ,这个值没有具体的数值,比其他所有分区的上限都要大,也包含空值。
示例:创建一个 RANGE 分区表。
```javascript
CREATE TABLE t_log_part_by_range (
log_id bigint NOT NULL
, log_value varchar(50)
, log_date timestamp NOT NULL
) PARTITION BY RANGE(UNIX_TIMESTAMP(log_date))
(
PARTITION M202001 VALUES LESS THAN(UNIX_TIMESTAMP('2020/02/01'))
, PARTITION M202002 VALUES LESS THAN(UNIX_TIMESTAMP('2020/03/01'))
, PARTITION M202003 VALUES LESS THAN(UNIX_TIMESTAMP('2020/04/01'))
, PARTITION M202004 VALUES LESS THAN(UNIX_TIMESTAMP('2020/05/01'))
, PARTITION M202005 VALUES LESS THAN(UNIX_TIMESTAMP('2020/06/01'))
, PARTITION M202006 VALUES LESS THAN(UNIX_TIMESTAMP('2020/07/01'))
, PARTITION M202007 VALUES LESS THAN(UNIX_TIMESTAMP('2020/08/01'))
, PARTITION M202008 VALUES LESS THAN(UNIX_TIMESTAMP('2020/09/01'))
, PARTITION M202009 VALUES LESS THAN(UNIX_TIMESTAMP('2020/10/01'))
, PARTITION M202010 VALUES LESS THAN(UNIX_TIMESTAMP('2020/11/01'))
, PARTITION M202011 VALUES LESS THAN(UNIX_TIMESTAMP('2020/12/01'))
, PARTITION M202012 VALUES LESS THAN(UNIX_TIMESTAMP('2021/01/01'))
);
```
RANGE 分区可以新增、删除分区。如果最后一个 RANGE 分区指定了 MAXVALUE ,则不能新增分区。
RANGE 分区要求表拆分键表达式的结果必须为整型,如果要按时间类型列做 RANGE 分区,则必须使用 timestamp 类型,并且使用函数 UNIX_TIMESTAMP 将时间类型转换为数值。这个需求也可以使用 RANGE COLUMNS 分区实现,就没有整型这个要求。
RANGE COLUMNS 分区
-------------------------
RANGE COLUMNS 分区作用跟 RANGE 分区基本类似,不同之处在于:
* RANGE COLUMNS 拆分列结果不要求是整型,可以是任意类型。
* RANGE COLUMNS 拆分列不能使用表达式。
* RANGE COLUMNS 拆分列可以写多个列(即列向量)。
RANGE COLUMNS 分区的简单语法格式如下:
```javascript
CREATE TABLE table_name (
column_name1 column_type
[, column_nameN column_type]
) PARTITION BY RANGE ( column_name1 [, column_name2] )
(
PARTITION p0 VALUES LESS THAN ( expr )
[, PARTITION pN VALUES LESS THAN (expr ) ]
[, PARTITION pX VALUES LESS THAN (maxvalue) ]
);
```
示例:创建一个 RANGE COLUMNS 分区
```javascript
CREATE TABLE t_log_part_by_range_columns (
log_id bigint NOT NULL
, log_value varchar(50)
, log_date date NOT NULL
) PARTITION BY RANGE COLUMNS(log_date)
(
PARTITION M202001 VALUES LESS THAN('2020/02/01')
, PARTITION M202002 VALUES LESS THAN('2020/03/01')
, PARTITION M202003 VALUES LESS THAN('2020/04/01')
, PARTITION M202004 VALUES LESS THAN('2020/05/01')
, PARTITION M202005 VALUES LESS THAN('2020/06/01')
, PARTITION M202006 VALUES LESS THAN('2020/07/01')
, PARTITION M202007 VALUES LESS THAN('2020/08/01')
, PARTITION M202008 VALUES LESS THAN('2020/09/01')
, PARTITION M202009 VALUES LESS THAN('2020/10/01')
, PARTITION M202010 VALUES LESS THAN('2020/11/01')
, PARTITION M202011 VALUES LESS THAN('2020/12/01')
, PARTITION M202012 VALUES LESS THAN('2021/01/01')
, PARTITION MMAX VALUES LESS THAN MAXVALUE
);
```
列表(LIST)分区
-------------------
LIST 分区使得您可以显式的控制记录行如何映射到分区,具体方法是为每个分区的分区键指定一组离散值列表,这点跟 RANGE 分区和 HASH 分区都不同。LIST 分区的优点是可以方便的对无序或无关的数据集进行分区。LIST 分区的简单语法格式如下:
```javascript
CREATE TABLE table_name (
column_name1 column_type
[, column_nameN column_type]
) PARTITION BY LIST ( expr(column_name1) )
(
PARTITION p0 VALUES IN ( v01 [, v0N] )
[, PARTITION pN VALUES IN ( vN1 [, vNN] ) ]
[, PARTITION pX VALUES IN (default) ]
);
```
当使用列表分区时,需要遵守以下规则:
* 分区表达式结果必须是整型。
* 分区表达式只能引用一列,不能有多列(即列向量)。
示例:创建一个 LIST 分区表。
```javascript
CREATE TABLE t_part_by_list (
c1 BIGINT PRIMARY KEY
, c2 VARCHAR(50)
) PARTITION BY list(c1)
(
PARTITION p0 VALUES IN (1, 2, 3)
, PARTITION p1 VALUES IN (5, 6)
, PARTITION p2 VALUES IN (DEFAULT)
);
```
LIST 分区可以新增分区,指定新的不重复的列表。也可以删除分区。
LIST COLUMNS 分区
------------------------
LIST COLUMNS 分区作用跟 LIST 分区基本相同,不同之处在于:
* LIST COLUMNS 的拆分列不能是表达式。
* LIST COLUMNS 的拆分列可以是多列(即列向量)。
LIST COLUMNS 分区简单的语法格式如下:
```javascript
CREATE TABLE table_name (
column_name1 column_type
[, column_nameN column_type]
) PARTITION BY LIST COLUMNS ( column_name1 [, column_nameN ] )
(
PARTITION p0 VALUES IN ( v01 [, v0N] )
[, PARTITION pN VALUES IN ( vN1 [, vNN] ) ]
[, PARTITION pX VALUES IN (default) ]
);
```
示例:创建一个 LIST COLUMNS 分区
```javascript
CREATE TABLE t2 (
id varchar(64),
type varchar(16),
info varchar(512),
gmt_create datetime(6),
gmt_modified datetime(6),
partition_id varchar(2) GENERATED ALWAYS AS (substr(`id`,19,20)) VIRTUAL,
PRIMARY KEY (id)
) partition by list columns(partition_id)
(partition p0 values in ('00','01'),
partition p1 values in ('02','03'),
partition p2 values in (default));
```
哈希(HASH)分区
-------------------
HASH 分区适合于对不能用 RANGE 分区、LIST 分区方法的场景,它的实现方法简单,通过对分区键上的 HASH 函数值来散列记录到不同分区中。如果您的数据符合下列特点,使用 HASH 分区是个很好的选择:
* 不能指定数据的分区键的列表特征。
* 不同范围内的数据大小相差非常大,并且很难手动调整均衡。
* 使用 RANGE 分区后数据聚集严重。
* 并行 DML、分区剪枝和分区连接等性能非常重要。
示例:创建一个 HASH 分区表。
```javascript
CREATE TABLE ware(
w_id int
, w_ytd number(12,2)
, w_tax number(4,4)
, w_name varchar(10)
, w_street_1 varchar(20)
, w_street_2 varchar(20)
, w_city varchar(20)
, w_state char(2)
, w_zip char(9)
, primary key(w_id)
) PARTITION by hash(w_id) partitions 60;
```
HASH 分区不适合做删除操作。
组合分区
-------------
组合分区通常是先使用一种分区策略,然后在子分区再使用另外一种分区策略,适合于业务表的数据量非常大时。使用组合分区能发挥多种分区策略的优点。
在指定二级分区分区策略细节时,可以使用 SUBPARTITION TEMPLATE 子句。
示例:创建组合分区表。
```javascript
CREATE TABLE t_ordr_part_by_hash_range (o_w_id int
, o_d_id int
, o_id int
, o_c_id int
, o_carrier_id int
, o_ol_cnt int
, o_all_local int
, o_entry_d TIMESTAMP NOT NULL
, index idx_ordr(o_w_id, o_d_id, o_c_id, o_id) LOCAL
, primary key ( o_w_id, o_d_id, o_id, o_entry_d )
)
PARTITION BY hash(o_w_id)
SUBPARTITION BY RANGE(UNIX_TIMESTAMP(o_entry_d))
SUBPARTITION template
(
SUBPARTITION M202001 VALUES LESS THAN(UNIX_TIMESTAMP('2020/02/01'))
, SUBPARTITION M202002 VALUES LESS THAN(UNIX_TIMESTAMP('2020/03/01'))
, SUBPARTITION M202003 VALUES LESS THAN(UNIX_TIMESTAMP('2020/04/01'))
, SUBPARTITION M202004 VALUES LESS THAN(UNIX_TIMESTAMP('2020/05/01'))
, SUBPARTITION M202005 VALUES LESS THAN(UNIX_TIMESTAMP('2020/06/01'))
, SUBPARTITION M202006 VALUES LESS THAN(UNIX_TIMESTAMP('2020/07/01'))
, SUBPARTITION M202007 VALUES LESS THAN(UNIX_TIMESTAMP('2020/08/01'))
, SUBPARTITION M202008 VALUES LESS THAN(UNIX_TIMESTAMP('2020/09/01'))
, SUBPARTITION M202009 VALUES LESS THAN(UNIX_TIMESTAMP('2020/10/01'))
, SUBPARTITION M202010 VALUES LESS THAN(UNIX_TIMESTAMP('2020/11/01'))
, SUBPARTITION M202011 VALUES LESS THAN(UNIX_TIMESTAMP('2020/12/01'))
, SUBPARTITION M202012 VALUES LESS THAN(UNIX_TIMESTAMP('2021/01/01'))
, SUBPARTITION MMAX VALUES LESS THAN MAXVALUE
)
partitions 16;
CREATE TABLE t_log_part_by_range_hash (
log_id int NOT NULL
, log_value varchar(50)
, log_date TIMESTAMP NOT NULL
, PRIMARY key(log_id, log_date)
) PARTITION BY RANGE(UNIX_TIMESTAMP(log_date))
SUBPARTITION BY HASH(log_id) SUBPARTITIONS 16
(
PARTITION M202001 VALUES LESS THAN(UNIX_TIMESTAMP('2020/02/01'))
, PARTITION M202002 VALUES LESS THAN(UNIX_TIMESTAMP('2020/03/01'))
, PARTITION M202003 VALUES LESS THAN(UNIX_TIMESTAMP('2020/04/01'))
, PARTITION M202004 VALUES LESS THAN(UNIX_TIMESTAMP('2020/05/01'))
, PARTITION M202005 VALUES LESS THAN(UNIX_TIMESTAMP('2020/06/01'))
, PARTITION M202006 VALUES LESS THAN(UNIX_TIMESTAMP('2020/07/01'))
, PARTITION M202007 VALUES LESS THAN(UNIX_TIMESTAMP('2020/08/01'))
, PARTITION M202008 VALUES LESS THAN(UNIX_TIMESTAMP('2020/09/01'))
, PARTITION M202009 VALUES LESS THAN(UNIX_TIMESTAMP('2020/10/01'))
, PARTITION M202010 VALUES LESS THAN(UNIX_TIMESTAMP('2020/11/01'))
, PARTITION M202011 VALUES LESS THAN(UNIX_TIMESTAMP('2020/12/01'))
, PARTITION M202012 VALUES LESS THAN(UNIX_TIMESTAMP('2021/01/01'))
, PARTITION MMAX VALUES LESS THAN MAXVALUE
);
```

View File

@ -0,0 +1,28 @@
分区表的索引
===========================
分区表的查询性能跟 SQL 中条件有关。当 SQL 中带上拆分键时,OceanBase 会根据条件做分区剪枝,只用搜索特定的分区即可;如果没有拆分键,则要扫描所有分区。
分区表也可以通过创建索引来提升性能。跟分区表一样,分区表的索引也可以分区或者不分区。
* 如果分区表的索引不分区,就是一个全局索引(GLOBAL),是一个独立的分区,索引数据覆盖整个分区表。
* 如果分区表的索引分区了,根据分区策略又可以分为两类。一是跟分区表保持一致的分区策略,则每个索引分区的索引数据覆盖相应的分区表的分区,这个索引又叫本地索引(LOCAL)。
建议尽可能的使用本地索引,只有在有必要的时候才使用全局索引。其原因是全局索引会降低 DML 的性能,DML 可能会因此产生分布式事务。
通常创建索引时默认都是全局索引,本地索引需要在后面增加关键字 LOCAL 。
示例:创建分区表的本地索引。
```javascript
CREATE INDEX idx_log_date ON t_log_part_by_range_hash(log_date) LOCAL;
```

View File

@ -0,0 +1,70 @@
分区表使用建议
============================
通常当表的数据量非常大,以致于可能使数据库空间紧张,或者由于表非常大导致相关 SQL 查询性能变慢时,可以考虑使用分区表。
使用分区表时要选择合适的拆分键以及拆分策略。如果是日志类型的大表,根据时间类型的列做 RANGE 分区是最合适的。如果是并发访问非常高的表,结合业务特点选择能满足绝大部分核心业务查询的列作为拆分键是最合适的。无论选哪个列做为分区键,都不大可能满足所有的查询性能。
分区表中的全局唯一性需求可以通过主键约束和唯一约束实现。OceanBase 数据库的分区表的主键约束和唯一键约束必须包含拆分键。唯一约束也是一个全局索引。全局唯一的需求也可以通过本地唯一索引实现,只需要在唯一索引里包含拆分键。
**示例:创建有唯一性需求的分区表**
```javascript
obclient> CREATE TABLE account(
id bigint NOT NULL PRIMARY KEY
, name varchar(50) NOT NULL UNIQUE
, value number NOT NULL
, gmt_create timestamp DEFAULT current_timestamp NOT NULL
, gmt_modified timestamp DEFAULT current_timestamp NOT NULL
) PARTITION BY HASH(id) PARTITIONS 16;
Query OK, 0 rows affected (0.16 sec)
obclient> CREATE TABLE account2(
id bigint NOT NULL PRIMARY KEY
, name varchar(50) NOT NULL
, value number NOT NULL
, gmt_create timestamp DEFAULT current_timestamp NOT NULL
, gmt_modified timestamp DEFAULT current_timestamp NOT NULL
) PARTITION BY HASH(id) PARTITIONS 16;
Query OK, 0 rows affected (0.11 sec)
obclient> CREATE UNIQUE INDEX account2_uk ON account2(name, id) LOCAL ;
Query OK, 0 rows affected (0.73 sec)
obclient> show indexes from account;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
| account | 0 | PRIMARY | 1 | id | A | NULL | NULL | NULL | | BTREE | available | | YES |
| account | 0 | name | 1 | name | A | NULL | NULL | NULL | | BTREE | available | | YES |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
2 rows in set (0.01 sec)
obclient> show indexes from account2;
+----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible |
+----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
| account2 | 0 | PRIMARY | 1 | id | A | NULL | NULL | NULL | | BTREE | available | | YES |
| account2 | 0 | account2_uk | 1 | name | A | NULL | NULL | NULL | | BTREE | available | | YES |
| account2 | 0 | account2_uk | 2 | id | A | NULL | NULL | NULL | | BTREE | available | | YES |
+----------+------------+-------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+-----------+---------------+---------+
3 rows in set (0.00 sec)
obclient> SELECT * FROM information_schema.`TABLE_CONSTRAINTS` WHERE table_schema='TPCCDB' AND table_name LIKE 'ACCOUNT%';
+--------------------+-------------------+-----------------+--------------+------------+-----------------+
| CONSTRAINT_CATALOG | CONSTRAINT_SCHEMA | CONSTRAINT_NAME | TABLE_SCHEMA | TABLE_NAME | CONSTRAINT_TYPE |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+
| def | tpccdb | PRIMARY | tpccdb | account | PRIMARY KEY |
| def | tpccdb | name | tpccdb | account | UNIQUE |
| def | tpccdb | PRIMARY | tpccdb | account2 | PRIMARY KEY |
| def | tpccdb | account2_uk | tpccdb | account2 | UNIQUE |
+--------------------+-------------------+-----------------+--------------+------------+-----------------+
4 rows in set (0.02 sec)
```

View File

@ -0,0 +1,21 @@
关于表组
=========================
表组是表的属性,会影响多个表的分区在 OceanBase 机器上的分布特征。
不同表的分区有可能分布在不同的节点上,当两个表做表连接查询时,OceanBase 会跨节点请求数据,执行时间就跟节点间请求延时有关。在 SQL 调优时,OceanBase 建议对业务上关系密切的表,设置相同的表组。OceanBase 对于同一个表组中的表的同号分区会管理为一个分区组。同一个分区组中的分区,OceanBase 会尽可能的分配到同一个节点内部,这样就可以规避跨节点的请求。
创建表组时,首先要规划好表组的用途。如果是用于普通表的属性,表组就不用分区;如果是用于分区表的属性,表组就要指定分区策略,并且要跟分区表的分区策略保持一致。
示例:创建表组
```javascript
obclient> create tablegroup tpcc_group partition by hash partitions 6 ;
Query OK, 0 rows affected (0.03 sec)
obclient>
```

View File

@ -0,0 +1,48 @@
创建表时指定表组
=============================
表组可以在创建表的时候指定,SQL 查询语法格式如下:
```javascript
CREATE TABLE table_name (
column_name data_type [, column_name data_type]
) TABLEGROUP tablegroup_name ;
```
**示例:创建表时指定表组。**
如下创建订单表和订单明细表,业务上这两个表经常要关联查询,所以建议放到同一个表组中。
```javascript
create table ordr (
o_w_id int
, o_d_id int
, o_id int
, o_c_id int
, o_carrier_id int
, o_ol_cnt int
, o_all_local int
, o_entry_d date
, index iordr(o_w_id, o_d_id, o_c_id, o_id) local
, primary key ( o_w_id, o_d_id, o_id )
)tablegroup tpcc_group partition by hash(o_w_id) partitions 6;
create table ordl (
ol_w_id int
, ol_d_id int
, ol_o_id int
, ol_number int
, ol_delivery_d date
, ol_amount decimal(6, 2)
, ol_i_id int
, ol_supply_w_id int
, ol_quantity int
, ol_dist_info char(24)
, primary key (ol_w_id, ol_d_id, ol_o_id, ol_number )
)tablegroup tpcc_group partition by hash(ol_w_id) partitions 6;
```

View File

@ -0,0 +1,36 @@
查看表组信息
===========================
使用命令 SHOW TABLEGROUPS 和 SHOW CREATE TABLE 来查看表组信息。
示例:查看表组信息和定义
```javascript
obclient> show tablegroups;
+-----------------+------------+---------------+
| Tablegroup_name | Table_name | Database_name |
+-----------------+------------+---------------+
| oceanbase | NULL | NULL |
| tpcc_group | cust | tpccdb |
| tpcc_group | dist | tpccdb |
| tpcc_group | hist | tpccdb |
| tpcc_group | nord | tpccdb |
| tpcc_group | ordl | tpccdb |
| tpcc_group | ordr | tpccdb |
| tpcc_group | stok | tpccdb |
| tpcc_group | ware | tpccdb |
+-----------------+------------+---------------+
9 rows in set (0.01 sec)
obclient> show create tablegroup tpcc_group\G
*************************** 1. row ***************************
Tablegroup: tpcc_group
Create Tablegroup: CREATE TABLEGROUP IF NOT EXISTS `tpcc_group` BINDING = FALSE
partition by hash partitions 6
1 row in set (0.00 sec)
```

View File

@ -0,0 +1,49 @@
向表组中增加表
============================
如果表创建的时候没有指定表组,也可以事后加入到表组中。有两种方法:一是修改表的表组属性,二是使用 ALTER TABLEGROUP ADD 语法。
* 示例:修改表的表组属性
**说明**
修改表的表组属性时名字不用单引号,否则会区分大小写。
```javascript
obclient> alter table ordr tablegroup=tpcc_group;
Query OK, 0 rows affected (0.04 sec)
obclient> alter table ordl tablegroup=tpcc_group;
Query OK, 0 rows affected (0.04 sec)
```
* 示例:向表组中加入表
向表组中加入表的前提是表的分区策略跟表组的分区策略保持一致。
```javascript
obclient> alter table ordr tablegroup='';
Query OK, 0 rows affected (0.04 sec)
obclient> alter table ordl tablegroup='';
Query OK, 0 rows affected (0.03 sec)
obclient> alter tablegroup tpcc_group add ordr, ordl ;
Query OK, 0 rows affected (0.03 sec)
obclient>
```

View File

@ -0,0 +1,32 @@
删除表组
=========================
如果要删除表组,得先确认表组中没有表。具体方法就是从表组中删除表,或者将相关表的表组属性清空。
示例如下:
```javascript
obclient> show tablegroups;
+-----------------+------------+---------------+
| Tablegroup_name | Table_name | Database_name |
+-----------------+------------+---------------+
| oceanbase | NULL | NULL |
| tpcc_group | cust | tpccdb |
| tpcc_group | dist | tpccdb |
| tpcc_group | hist | tpccdb |
| tpcc_group | nord | tpccdb |
| tpcc_group | ordl | tpccdb |
| tpcc_group | ordr | tpccdb |
| tpcc_group | stok | tpccdb |
| tpcc_group | ware | tpccdb |
+-----------------+------------+---------------+
9 rows in set (0.01 sec)
obclient> drop tablegroup tpcc_group;
ERROR 4615 (HY000): tablegroup is not empty
obclient>
```

View File

@ -0,0 +1,22 @@
创建视图
=========================
可以使用 CREATE VIEW 语句来创建视图。
示例:创建视图 stock_item,该视图内容取自 stock 和 item 两张表,两张表做表连接就得到这个视图。
```javascript
obclient> CREATE VIEW stock_item
AS
SELECT /*+ leading(s) use_merge(i) */
i_price, i_name, i_data, s_i_id, s_w_id, s_order_cnt, s_ytd, s_remote_cnt, s_quantity, s_data, s_dist_01, s_dist_02, s_dist_03, s_dist_04, s_dist_05, s_dist_06, s_dist_07, s_dist_08, s_dist_09, s_dist_10
FROM stok s, item i
WHERE s.s_i_id = i.i_id;
Query OK, 0 rows affected (0.01 sec)
```
查看更多创建视图的选项,请参见《SQL参考(MySQL模式)》。

View File

@ -0,0 +1,21 @@
修改视图
=========================
可以使用 CREATE OR REPLACE VIEW 语句来对视图进行修改。
示例:修改视图 stock_item。
```javascript
obclient> CREATE OR REPLACE VIEW stock_item
AS
SELECT /*+ leading(s) use_merge(i) */
i_price, i_name, i_data, s_i_id, s_w_id, s_order_cnt, s_ytd, s_remote_cnt, s_quantity, s_data, s_dist_01, s_dist_02, s_dist_03, s_dist_04, s_dist_05, s_dist_06, s_dist_07, s_dist_08, s_dist_09, s_dist_10
FROM stok s, item i
WHERE s.s_i_id = i.i_id;
Query OK, 0 rows affected (0.02 sec)
```

View File

@ -0,0 +1,8 @@
删除视图
=========================
删除视图使用 DROP VIEW 语句。
删除视图并不会删除视图引用的表。如果视图被其他视图所引用,视图删除后将会导致依赖当前视图的其他视图查询失败。