SQL 是一种“描述型”语言。与“过程型”语言不同,用户在使用 SQL 时,只描述了“要做什么”,而不是“怎么做”
数据库在接收到SQL查询时,必须为其生成一个“执行计划”。OceanBase的执行计划本质上是由物理操作符构成的一棵执行树
执行树从形状上可以分为“左深树”、“右深树”和“多枝树”三种(参见下图)。OceanBase的优化器在生成连接顺序时主要考虑左深树的连接形式。
执行计划展示
通过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)-计划形状与算子信息
Explain输出的第一部分是执行计划的树形结构展示。其中每一个操作在树中的层次通过其在OPERATOR中的缩进予以展示:
执行计划展示(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)
执行计划展示-示例
如下示例可以看出要访问的表为IDX_a这张索引表,表的主键为(c2,c1),扫描的范围是全表扫描。
实时执行计划展示
实时执行计划展示可以展示 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这四列的值,否则系统将返回空集
实时执行计划展示
首先通过(g)v$plan_cache_plan_stat虚拟表查询到SQL 在计划缓存中对应的plan_id
实时执行计划展示
通过查询(g)v$plan_cache_plan_explain这张虚拟表来展示某条SQL在计划缓存中的执行计划
EXPLAIN与实时执行计划的对比
EXPLAIN命令的输出逻辑执行计划:
v$plan_cache_plan_explain输出的实时执行计划:
查看执行计划的几种其它方式
EXPLAIN|DESCRIBE|DESC方式查看执行计划
{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;
通过v$sql_audit查看每一次SQL请求的来源、执行状态等统计信息
select * from v$sql_audit;