OceanBase
OceanBase 使用通用服务器硬件,依赖本地存储,分布式部署在多个服务器上,每个服务器都是对等的,数据库内的 SQL 执行引擎具有分布式执行能力,每台服务器上运行一个observer单进程数据库实例。
1. 基本概念
OceanBase架构图:
名词解释:
Zone:
zone代表可用区,由若干个服务器组成,可用区是一个逻辑概念,表示集群内具有相似硬件可用性的一组节点,也可以把zone当成一个数据中心,上图就有3个可用区Zone1、Zone2、Zone3,每个可用区内有2台服务器节点,共6台服务器。
Server:
server代表服务器,上图共有6台服务器,属于不同可用区Zone。
Tenant:
tenant代表租户,OceanBase内置多租户特性,每个租户是一个独立的数据库,一个租户能够在租户级别设置租户的分布式部署方式。租户之间 CPU、内存和 IO 都是隔离的,上图有3个租户:Tenant1、Tenant2、Tenant SYS。
Tenant SYS为系统租户,集群创建时就自动创建了系统租户,且不可扩容。
Unit:
unit是租户在 OBServer 上的容器,描述租户在 OBServer 上的可用资源(CPU、MEMORY 等)。一个租户在一个 OBServer 只能同时存在一个 Unit,如:Tenant1租户,在6台Server上分别都运行了一个Unit。
LogStream:
logstream表示日志流,是由 OceanBase 数据库自动创建和管理的实体,它代表了一批数据的集合,可在上图中看到有LogStream Leader、Follower,且分布在不同Server上,它通过 Paxos 协议实现了多副本日志同步,保证副本间数据的一致性,实现了数据的高可用。
P 表示分区:
Partition是用户创建的逻辑对象,是划分和管理表数据的一种机制,分区表会有多个分片,由OceanBase自动管理,单表最多配置8192个分片,所以单表能存储大量数据(官方号称万亿行)。
每个分片默认有3个副本,用于故障容灾,也可以用于分散读取压力,同一个租户在一个可用区内的数据只有一个副本,上图中Tenant1租户P1分片在Unit1、Unit2、Unit3上都存在,且在Unit1上绿色P1是主分片。
OceanBase同时存在两份数据MemTable和SSTable,SQL操作插入、更新、删除等首先写入 MemTable(内存),速度快,依赖 Paxos 协议实现了多副本日志同步,保障数据不丢失,历史存量数据在SSTable里面 ,在每天的业务低峰期,系统会将所有的 MemTable 合并成SSTable,操作历史数据时,由于写到了内存中,而SSTable中也保存了一份,所以根据版本号对同一条数据进行区分,保证数据一致性。
OceanBase 的数据库实例内部由不同的组件相互协作,这些组件从底层向上由存储层、复制层、均衡层、事务层、SQL 层、接入层组成。
2. OceanBase的部署方案
方案一:同城三机房三副本部署
特点:
- 同城 3 个机房组成一个集群(每个机房是一个 Zone),机房间网络延迟一般在 0.5 ~ 2 ms 之间。
- 机房级灾难时,剩余的两份副本依然是多数派,依然可以同步 RedoLog 日志,保证 RPO=0。
- 无法应对城市级的灾难。
方案二:三地五中心五副本部署
特点:
- 三个城市,组成一个 5 副本的集群。
- 任何一个 IDC 或者城市的故障,依然构成多数派,可以确保 RPO=0。
- 由于 3 份以上副本才能构成多数派,但每个城市最多只有 2 份副本,为降低时延,城市 1 和城市 2 应该离得较近,以降低同步 RedoLog 的时延。
方案三:同城两机房 “主-备” 部署
特点:
- 每个机房都部署一个 OceanBase 集群,一个为主库一个为备库;每个集群有自己单独的 Paxos group,多副本一致性。
- “集群间” 通过 RedoLog 做数据同步,形式上类似传统数据库 “主从复制” 模式,从主库 “异步同步” 到备库,类似 Oracle Data Guard 中的 “最大性能” 模式。
3. SQL语法
OceanBase数据库社区版兼容MySQL语法,企业版兼容MySQL和Oracle语法
4. SpringBoot+MyBatis框架使用OceanBase数据库
- 修改pom文件,把MySQL驱动更换为OceanBase驱动包
<!-- OceanBase驱动包 --> <dependency> <groupId>com.oceanbase</groupId> <artifactId>oceanbase-client</artifactId> <version>2.4.3</version> </dependency>
- 修改连接配置信息
# oceanbase连接信息 spring.datasource.driverClassName=com.oceanbase.jdbc.Driver spring.datasource.url=jdbc:oceanbase://192.168.113.161:2883/employees? useSSL=false&useUnicode=true&characterEncoding=utf-8&useServerPrepStmts=true&rewriteBatchedStatements=true spring.datasource.username=root@mq_t1#zycluster spring.datasource.password=/aVi*H8(0%FS_YwZ-|dmo&[hjlT7pe@E
ODP 连接方式的常用格式有两种:用户名@租户名#集群名 或者 集群名:租户名:用户名;直连方式格式:用户名@租户名。
其余操作和使用MySQL一样
5. 执行计划分析
- 执行计划的描述
◼ SQL 是一种“描述型”语言。与“过程型”语言不同,用户在使用 SQL 时,只描述了“要做什么”,而不是“怎么
做”
◼ 数据库在接收到 SQL 查询时,必须为其生成一个“执行计划”。OceanBase 的执行计划本质上是由物理操作符构
成的一棵执行树
◼ 执行树从形状上可以分为“左深树”、“右深树”和“多枝树”三种(参见下图)。 OceanBase 的优化器在生成
连接顺序时主要考虑左深树的连接形式
--左深树
⚫
/ \
⚫ ⚫
/ \
⚫ ⚫
/ \
⚫ ⚫
--右深数
⚫
/ \
⚫ ⚫
/ \
⚫ ⚫
/ \
⚫ ⚫
--多枝树
⚫
/ \
⚫ ⚫
/ \ / \
⚫ ⚫⚫ ⚫
- 执行计划展示(EXPLAIN)
◼ 通过Explain命令查看优化器针对给定SQL生成的逻辑执行计划
◼ Explain不会真正执行给定的SQL,可以放心使用该功能而不用担心在性能调试中可能给系统性能带来影响
◼ Explain命令格式如下例所示,展示格式包括 BASIC、EXTENDED、PARTITIONS 等等,内容的详细程度有所区别
EXPLAIN [BASIC | EXTENDED | PARTITIONS | FORMAT = format_name] explainable_stmt
format_name:
{ TRADITIONAL | JSON }
explainable_stmt:
{ SELECT statement
| DELETE statement
| INSERT statement
| REPLACE statement
| UPDATE statement }
EXPLAIN BASIC SELECT statement ;
EXPLAIN EXTENDED SELECT statement ;
EXPLAIN PARTITIONS SELECT statement ;
EXPLAIN FORMAT =TRADITIONAL SELECT statement ;
EXPLAIN FORMAT =JSON SELECT statement ;
EXPLAIN BASIC DELETE statement ;
EXPLAIN EXTENDED DELETE statement ;
EXPLAIN PARTITIONS DELETE statement ;
EXPLAIN FORMAT =TRADITIONAL DELETE statement ;
EXPLAIN FORMAT =JSON DELETE statement ;
EXPLAIN BASIC INSERT statement ;
EXPLAIN EXTENDED INSERT statement ;
EXPLAIN PARTITIONS INSERT statement ;
EXPLAIN FORMAT =TRADITIONAL INSERT statement ;
EXPLAIN FORMAT =JSON INSERT statement ;
EXPLAIN BASIC REPLACE statement ;
EXPLAIN EXTENDED REPLACE statement ;
EXPLAIN PARTITIONS REPLACE statement ;
EXPLAIN FORMAT =TRADITIONAL REPLACE statement ;
EXPLAIN FORMAT =JSON REPLACE statement ;
EXPLAIN BASIC UPDATE statement ;
EXPLAIN EXTENDED UPDATE statement ;
EXPLAIN PARTITIONS UPDATE statement ;
EXPLAIN FORMAT =TRADITIONAL UPDATE statement ;
EXPLAIN FORMAT =JSON UPDATE statement ;
- 执行计划展示(EXPLAIN)-计划形状与算子信息
◼ Explain输出的第一部分是执行计划的树形结构展示。其中每一个操作在树中的层次通过其在OPERATOR中的缩进予
以展示:
|==========================================
|ID|OPERATOR |NAME|EST. ROWS|COST|
------------------------------------------
|0 |SORT | |1 |2763|
|1 | MERGE INNER JOIN | |1 |2735|
|2 | SORT | |1000 |1686|
|3 | TABLE SCAN |t2 |1000 |1180|
|4 | TABLE SCAN |t1 |1 |815 |
==========================================
(0)SORT
|
(1)MERGE JOIN
/ \
/ \
(2)SORT (4)TABLE SCAN
/
/
(3)TABLE SCAN
执行顺序为:3->2->4->1->0;
- 执行计划展示(EXPLAIN)-计划形状与算子信息
--执行计划各列含义
列名 含义
ID :执行树按照前序遍历的方式得到的编号(从0开始)
OPERATOR:操作算子的名称
NAME:对应表操作的表名(索引名)
EST. ROWS:估算的该操作算子的输出行数
COST:该操作算子的执行代价(微秒)
--常见的算子
类型 算子
表访问:table scan, table get
连接:NESTED-LOOP, BLK-NESTED-LOOP,Merge、hash
排序:sort,top-n sort
聚合:merge group-by,hash group-by,window function
分布式:exchange in/out remote/distribute
集合:union, except, intersect,minus
其他:limit, material, subplan, expression, count
- 执行计划展示(EXPLAIN)-操作算子详细输出
◼ Explain输出的第二部分是各操作算子的详细信息,包括输出表达式、过滤条件、分区信息以及各算子的独有信息,
包括排序键、连接键、下压条件等等:
Outputs & filters:
-------------------------------------
0 - output([t1.c1], [t1.c2], [t2.c1], [t2.c2]), filter(nil), sort_keys([t1.c1, ASC],
[t1.c2, ASC]), prefix_pos(1)
1 - output([t1.c1], [t1.c2], [t2.c1], [t2.c2]), filter(nil),
equal_conds([t1.c1 = t2.c2]), other_conds(nil)
2 - output([t2.c1], [t2.c2]), filter(nil), sort_keys([t2.c2, ASC])
3 - output([t2.c2], [t2.c1]), filter(nil),access([t2.c2], [t2.c1]), partitions(p0)
4 - output([t1.c1], [t1.c2]), filter(nil),access([t1.c1], [t1.c2]), partitions(p0)
- 执行计划展示(EXPLAIN)-示例
◼ 如下示例可以看出要访问的表为 t1_c2 这张索引表,表的主键为(c2, c1),扫描的范围是全表扫描。
OceanBase (root@oceanbase)> explain extended
select /*+ index(t1 t1_c2) */* from t1 where c3 = 5 and c1 = 6 order by c2, c3;
========================================
|ID|OPERATOR |NAME |EST. ROWS|COST|
----------------------------------------
|0 |TABLE SCAN|t1(t1_c2)|1 |1255|
========================================
Outputs & filters:
-------------------------------------
0 - output([t1.c1(0x7f1d520a0a98)], [t1.c2(0x7f1d520a0d98)],
[t1.c3(0x7f1d5209fbe0)]), filter([t1.c3(0x7f1d5209fbe0) = 5(0x7f1d5209f5d8)],
[t1.c1(0x7f1d520a0a98) = 6(0x7f1d520a0490)]),
access([t1.c3(0x7f1d5209fbe0)], [t1.c1(0x7f1d520a0a98)],
[t1.c2(0x7f1d520a0d98)]), partitions(p0),is_index_back=true, filter_before_indexback[false,true],
range_key([t1.c2(0x7f1d520a0d98)], [t1.c1(0x7f1d520a0a98)]),
range(MIN,MIN ; MAX,MAX)always true
- 实时执行计划展示
实时执行计划展示可以展示 SQL 的物理执行计划。而使用Explain命令,可以展示出当前优化器所生成的执行计划,
但该SQL在计划缓存中实际对应的计划可能与Explain的结果并不相同,造成这种现象的原因有很多,诸如统计信息
变化、用户session变量设置变化等等。为了确定该SQL在系统中实际使用的执行计划,有时还需要进一步分析计划
缓存中的物理执行计划。
OceanBase 数据库每个服务器的计划缓存都是独立的 。 用户可以通过查询(g)v$plan_cache_plan_explain 这张虚
拟表来展示某条SQL在计划缓存中的执行计划。其中有几个注意点:
◼ (g)v$plan_cache_plan_explain 这张虚拟表展示的计划为物理执行计划,在算子命名上会与 EXPLAIN 所展示
的逻辑执行计划有所不同
◼ 如果访问v$plan_cache_plan_explain,必须给定tenant_id和plan_id的值,否则系统将返回空集
◼ 如果访问gv$plan_cache_plan_explain,必须给定ip、port、tenant_id、plan_id这四列的值,否则系统将返
回空集
Step1:首先通过(g)v$plan_cache_plan_stat虚拟表查询到SQL 在计划缓存中对应的plan_id
select * from v$plan_cache_plan_stat
where tenant_id= 1001 and statement like 'insert into t1 values%'\G
***************************1. row ***************************
tenant_id: 1001
svr_ip:100.81.152.44
svr_port:15212
plan_id: 7
sql_id:0
type: 1
statement: insert into t1 values(1)
plan_hash:1
last_active_time:2016-05-28 19:08:57.416670
avg_exe_usec:0
slowest_exe_time:1970-01-01 08:00:00.000000
slowest_exe_usec:0
slow_count:0
hit_count:0
mem_used:8192
Step2:通过查询(g)v$plan_cache_plan_explain 这张虚拟表来展示某条SQL在计划缓存中的执行计划
SELECT * FROM v$plan_cache_plan_explain
WHERE tenant_id = 1001 AND plan_id = 7;
+---------+---------------+-------+--------+--------------------+------+------+------+
|TENANT_ID| IP | PORT |PLAN_ID | OPERATOR | NAME | ROWS | COST |
+---------+---------------+-------+--------+--------------------+------+------+------+
| 1001 | 192.168.8.121 | 15212 | 7 | PHY_ROOT_TRANSMIT | NULL | 0 | 0 |
| 1001 | 192.168.8.121 | 15212 | 7 | PHY_INSERT | NULL | 0 | 0 |
| 1001 | 192.168.8.121 | 15212 | 7 | PHY_EXPR_VALUES | NULL | 0 | 0 |
+---------+---------------+-------+--------+--------------------+------+------+------+
3 rows in set (0.01 sec)
- EXPLAIN与实时执行计划的对比
EXPLAIN命令的输出逻辑执行计划:
Query Plan: ==============================================
|ID|OPERATOR |NAME |EST. ROWS|COST |
---------------------------------------------------------
|0 |PX COORDINATOR | |392040000|270172176|
|1 | EXCHANGE OUT DISTR |:EX10000|392040000|233061644|
|2 | PX PARTITION ITERATOR| |392040000|233061644|
|3 | HASH JOIN | |392040000|233061644|
|4 | TABLE SCAN |t1 |200000 |132543 |
|5 | TABLE SCAN |t2 |200000 |132543 |
=========================================================
Outputs & filters:
-------------------------------------
0 - output([t1.c1]), filter(nil)
1 - output([t1.c1]), filter(nil), dop=1
2 - output([t1.c1]), filter(nil)
3 - output([t1.c1]), filter(nil),
equal_conds([t1.c1 = t2.c1]), other_conds(nil)
4 - output([t1.c1]), filter(nil),
access([t1.c1]), partitions(p[0-1])
5 - output([t2.c1]), filter(nil),
access([t2.c1]), partitions(p[0-1])
v$plan_cache_plan_explain 输出的实时执行计划:
+--------------------------+------+-----------+-----------
| OPERATOR | NAME | ROWS | COST
+--------------------------+------+-----------+-----------
| PHY_PX_FIFO_COORD | NULL | 392039999 | 270172175
| PHY_PX_REDUCE_TRANSMIT | NULL | 392039999 | 233061643
| PHY_GRANULE_ITERATOR | NULL | 392039999 | 233061643
| PHY_HASH_JOIN | NULL | 392039999 | 233061643
| PHY_TABLE_SCAN | t1 | 200000 | 132542
| PHY_TABLE_SCAN | t2 | 200000 | 132542
+--------------------------+------+-----------+-----------
EXPLAIN命令的输出逻辑执行计划: v$plan_cache_plan_explain 输出的实时执行计划:
v$plan_cache_plan_explain中的数据没有类似explain输出的第二部份的各操作算子的详细信息
总结:
可以看到真实的执行计划中,里面有关键字前缀:PHY_;这与Oracle的执行计划有所不同。
- 查看执行计划的几种其它方式
◼ EXPLAIN|DESCRIBE|DESC方式查看执行计划
select * from v$sql_audit;
{EXPLAIN | DESCRIBE | DESC}
[BASIC | OUTLINE | EXTENDED | EXTENDED_NOADDR | PARTITIONS | FORMAT = {TRADITIONAL|
JSON}]
{SELECT statement | DELETE statement | INSERT statement | REPLACE statement| UPDATE
statement}
◼ 通过SQL Trace查看执行过程信息及各阶段的耗时
SET ob_enable_trace_log = 1;
SHOW TRACE;
--用法:
SET ob_enable_trace_log = 1;
SQL STATEMENT;
SHOW TRACE;
◼ 通过v$sql_audit 查看每一次SQL请求的来源、执行状态等统计信息
select * from v$sql_audit;
--查看执行计划的方法。
DESCRIBE/DESC/EXPLAIN BASIC SELECT statement;
DESCRIBE/DESC/EXPLAIN OUTLINE SELECT statement;
DESCRIBE/DESC/EXPLAIN EXTENDED SELECT statement;
DESCRIBE/DESC/EXPLAIN EXTENDED_NOADDR SELECT statement;
DESCRIBE/DESC/EXPLAIN PARTITIONS SELECT statement;
DESCRIBE/DESC/EXPLAIN FORMAT =TRADITIONAL SELECT statement;
DESCRIBE/DESC/EXPLAIN FORMAT =JSON SELECT statement;
DESCRIBE/DESC/EXPLAIN BASIC DELETE statement;
DESCRIBE/DESC/EXPLAIN OUTLINE DELETE statement;
DESCRIBE/DESC/EXPLAIN EXTENDED DELETE statement;
DESCRIBE/DESC/EXPLAIN EXTENDED_NOADDR DELETE statement;
DESCRIBE/DESC/EXPLAIN PARTITIONS DELETE statement;
DESCRIBE/DESC/EXPLAIN FORMAT =TRADITIONAL DELETE statement;
DESCRIBE/DESC/EXPLAIN FORMAT =JSON DELETE statement;
DESCRIBE/DESC/EXPLAIN BASIC INSERT statement;
DESCRIBE/DESC/EXPLAIN OUTLINE INSERT statement;
DESCRIBE/DESC/EXPLAIN EXTENDED INSERT statement;
DESCRIBE/DESC/EXPLAIN EXTENDED_NOADDR INSERT statement;
DESCRIBE/DESC/EXPLAIN PARTITIONS INSERT statement;
DESCRIBE/DESC/EXPLAIN FORMAT =TRADITIONAL INSERT statement;
DESCRIBE/DESC/EXPLAIN FORMAT =JSON INSERT statement;
DESCRIBE/DESC/EXPLAIN BASIC REPLACE statement;
DESCRIBE/DESC/EXPLAIN OUTLINE REPLACE statement;
DESCRIBE/DESC/EXPLAIN EXTENDED REPLACE statement;
DESCRIBE/DESC/EXPLAIN EXTENDED_NOADDR REPLACE statement;
DESCRIBE/DESC/EXPLAIN PARTITIONS REPLACE statement;
DESCRIBE/DESC/EXPLAIN FORMAT =TRADITIONAL REPLACE statement;
DESCRIBE/DESC/EXPLAIN FORMAT =JSON REPLACE statement;
DESCRIBE/DESC/EXPLAIN BASIC UPDATE statement;
DESCRIBE/DESC/EXPLAIN OUTLINE UPDATE statement;
DESCRIBE/DESC/EXPLAIN EXTENDED UPDATE statement;
DESCRIBE/DESC/EXPLAIN EXTENDED_NOADDR UPDATE statement;
DESCRIBE/DESC/EXPLAIN PARTITIONS UPDATE statement;
DESCRIBE/DESC/EXPLAIN FORMAT =TRADITIONAL UPDATE statement;
DESCRIBE/DESC/EXPLAIN FORMAT =JSON UPDATE statement;
OceanBase基础知识原文链接:
https://blog.csdn.net/zhuyu19911016520/article/details/135574673
OceanBase执行计划分析原文链接:
http://t.csdnimg.cn/AdFwa