绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
GaussDB T 性能调优——SQL问题分析之分析执行计划
2020-03-16 11:11:30

摘要:本文介绍GaussDB T 数据库SQL 问题分析之分析执行计划。

分析执行计划

执行计划是数据库优化器为高效地运行SQL语句(包括SELECT、UPDATE、INSERT、
DELETE)而选择执行的一系列操作,可以通过EXPLAIN语句来查看执行计划,帮助分
析定位SQL性能问题。

执行计划主要显示以下信息:

● 表的扫描方式:就是访问表中数据的方式,包括全表扫描和索引扫描.
● 表的连接顺序:就是以哪张表作为驱动表来连接其他表的先后访问顺序。
● 表的连接方式:就是两个表获得满足条件的数据时的连接过程。主要有三种表连接方式,嵌套循环(NESTED LOOPS)、哈希连接(HASH JOIN)和排序-合并连接(SORT MERGE JOIN)。

除此之外,执行计划还会展示执行顺序和每步操作的成本、访问表的分区信息、条件过滤、排序、去重等操作等内容。查看DML类语句的执行计划,能帮助分析SQL执行是否使用了优的执行计划,以决定是否优化SQL语句。

执行顺序:执行计划显示是按照层次逐步缩进的,一般来说缩进多的那一步,先执行,如果缩进相同,则上面的步骤优先执行。对于每一步执行,都有对应操作的描述和相关信息。

以下面的SQL语句为例:

SELECT t1.id, t2.c_int FROM autotrace_1 t1 
JOIN autotrace_2 t2 
ON t1.id = t2.id 
LEFT JOIN autotrace_3 t3 
ON t2.c_int = t3.c_int 
WHERE t3.id < 11 AND t2.id IN (SELECT c_int AS id FROM autotrace_2 ) ORDER BY t1.id LIMIT 3;

执行计划如下:
image.png

根据执行顺序规则,先从开头一直连续向右看,直到右边也就是缩进深的一行:TABLE ACCESS FULL,所以先执行扫描表autotrace_2,扫描方式是全表扫描。

image.png

然后寻找上一层级,找到并列的两行SUBSELECT、TABLE ACCESS FULL,根据同级的靠上的先执行原则,所以是先将AUTOTRACE_2表的扫描结果作为子查询表,然后再执行扫描AUTOTRACE_2(别名为T2),后将这两个扫描结果做半连接操作,连接方式是HASH JOIN SEMI,括号中的L表示是左边也就是靠上的子查询表建的哈希表。

image.png

结合SQL可以看出数据库对于条件中的IN + 子查询这种情况作了优化处理,实际执行是将原SQL中的IN改写成EXISTS,这样可以便于将exists改写为table,与其它table做Hash Semi或者Hash Anti。

例如:
Select * from t1 where f1 in (select f1 from t2 where t2.f2=t1.f2)

Select * from t1 where exists (select 1 from t2 where t2.f2=t1.f2 and
t2.f1=t1.f1)

再往上一层缩进查看,半连接操作的结果与AUTOTRACE_1表的扫描结果执行两表关联,连接方式是HASH JOIN,并且是左表建哈希表。

image.png

依次往上层查看,哈希连接的结果与AUTOTRACE_3表的扫描结果再做关联操作,连接方式同样是HASH JOIN。结合SQL中T1和T2表的join结果与T3表做的是左外连接,但实际执行计划是内连接,说明数据库内部做了外连接消除的优化,这里是由于WHERE条件中t3.id < 11是左连接右表的过滤条件,该过滤条件与NULL比较恒为FALSE,因此可以转为INNER JOIN。

image.png

后HASH JOIN的结果再依次执行排序QUERY SORT ORDER BY 和限制查询LIMIT操作,生成终的结果集。

从执行计划中可以看出由于没有建索引,表的访问全是全表扫描,若数据量较大则执行效率不高,因此可以考虑建立索引来优化SQL,一般在关联条件或过滤条件字段上建立索引,由于SQL语句中T1表涉及到的字段只有t1.id,T2表的过滤条件字段是t2.id,关联条件字段是t2.c_int,因此分别在这些字段上建立索引。

create index trace_idx_1 on autotrace_1(id);
create index trace_idx_2 on autotrace_2(id,c_int);

再通过explain语句查看建立索引后该SQL的执行计划:

image.png

可以发现T2表走的索引快速全扫描,因为索引TRACE_IDX_2是个组合索引,包含了SQL语句中涉及T2表所有的所有字段,所以T2表只需要访问索引,不需要访问表。该扫描方式索引返回结果是无序的,性能优于全表扫描,支持多块读,优于全索引扫描,一般适用于只需要访问索引就能获得结果的场景。

T1表则是索引范围扫描,这是常用的索引扫描方式,性能好跟索引扫描一样,差跟索引全扫描一样,当需要在索引中扫描大量数据并且需要访问表时性能很差,该扫描方式索引返回结果是有序的。

一般如果表上存在选择性很好的索引,却走了全表扫描,而且是大表的全表扫描,就说明表的访问方式可能存在问题;若大表上没有合适的索引而走了全表扫描,就需要分析能否建立索引,或者是否能选择更合适的表连接方式和连接顺序以提高效率。

建立索引一般能提升执行效率,但索引建的不好则无法优化查询效率,如何建立有效的索引有以下几点:

– 较频繁的作为查询条件的字段应该创建索引
– 性太差的字段不适合单独创建索引,即使频繁作为查询条件
– 更新非常频繁的字段不适合创建索引
– 复合索引应建立在查询频繁的少数字段上,并且应考虑列的顺序
建索引后除了影响表的扫描方式以外,通过执行计划可以看出,表的关联方式也变了

image.png

原本表T2和表T1之间走的HASH JOIN,现在改走NESTED LOOPS,这是因为 AUTOTRACE_2表做完HASH JOIN SEMI之后的结果集较小,因此作为驱动表较为合适,又由于被驱动表AUTOTRACE_3在关联字段上有索引,因此这里采用嵌套循环的方式。

多表连接方式的选择是影响执行效率的重要因素之一,嵌套循环和哈希连接一般有以下特点:

● 嵌套循环
嵌套循环是重要的连接方式,尤其是在实时性比较高的系统中,因为这种系统的查询要求快速返回,不能访问很多的数据块,而这正是嵌套循环适用的场景。

嵌套循环的使用场景:
– 驱动表的结果集小(该表过滤条件过滤后),选择驱动表非常重要。
– 被驱动表的连接列上有索引。
– 驱动表和被驱动表连接匹配的数据量小,即扫描被驱动表连接列的索引的次
数少。

● 哈希连接
Hash连接是非常常用的连接方式,它有以下特点:
– 适用于较大数据集的连接,并且连接条件必须是等值连接。
– 尽量选择小的数据集作为驱动表在内存中生成hash表。
– 设置一个较大的Temp Bñffžr可以加快hash连接的速度,避免使用临时表空间。
– 多表连接时同样要注意连接顺序,中间结果集尽量小,少做无用功。
Hash连接相对与嵌套循环,它实际上是通过空间来换取时间,因为它需要保存hash表,占用较大的内存,在临时表空间不足的情况下是可能报错的,而嵌套循环一般不会报错,但可能非常慢。

分布式执行计划

分布式涉及CN和DN两个部分,所以分布式的执行计划也分为两个部分:CN的执行计
划、DN的执行计划。

● DN执行计划
DN的执行计划和单机的执行计划完全相同。

● CN执行计划
CN的执行计划也叫分布式执行计划,相比较单机的执行计划,分布式执行计划主要分为两个功能:
– 分布式执行计划中增加了一个特有的REMOTE_SCAN算子,REMOTE_SCAN算子可以把其它算子合并成一个整体直接下推到DN上执行。
– 分布式执行计划可以对各DN返回的执行结果进行二次的归并汇总计算。

示例

● 把SCAN算子作为REMOTE SCAN,下推到DN执行

explain select * from t1;
EXPLAIN PLAN OUTPUT 
----------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------
| Id | Description | Owner | Name | Rows | Cost | Bytes | Remark |
---------------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | | | |
| 1 | REMOTE SCAN | | | | | | PUSHDOWN SQL: SELECT AA,BB FROM 
SHARDING_REGRESS.T1 |
---------------------------------------------------------------------------------------------------------------------

● 把JOIN和SCAN两个算子作为REMOTE SCAN,下推到DN执行。

explain select a.aa,b.aa from t1 a join t2 b on a.aa=b.aa;
EXPLAIN PLAN OUTPUT 
----------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------
| Id | Description | Owner | Name | Rows | Cost | Bytes | 
Remark |
-----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------
| 0 | SELECT STATEMENT | | | | | 
| |
| 1 | REMOTE SCAN | | | | | | PUSHDOWN SQL: SELECT A.AA,B.AA FROM 
SHARDING_REGRESS.T1 A INNER JOIN SHARDING_REGRESS.T2 B ON A.AA = B.AA |
-----------------------------------------------------------------------------------------------------------------------
----------------------------------------------------

● 把ORDER和SCAN两个算子作为REMOTE SCAN,下推到DN执行,CN对各DN返回的结果进行二次排序(MERGE SORT)

explain select * from t1 order by bb;
EXPLAIN PLAN OUTPUT 
----------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
----------------------------------------
| Id | Description | Owner | Name | Rows | Cost | Bytes | 
Remark |
-----------------------------------------------------------------------------------------------------------------------
----------------------------------------
| 0 | SELECT STATEMENT | | | | | 
| |
| 1 | REMOTE SCAN (MERGE SORT) | | | | | | PUSHDOWN SQL: SELECT AA,BB 
FROM SHARDING_REGRESS.T1 ORDER BY SHARDING_REGRESS.T1.BB |
-----------------------------------------------------------------------------------------------------------------------
----------------------------------------
分享好友

分享这个小栈给你的朋友们,一起进步吧。

GaussDB_数据库
创建时间:2020-01-06 16:21:44
华为GaussDB数据库小栈
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • GaussDB_数据库
    专家
戳我,来吐槽~