摘要:本文主要介绍如何详细解读基于gaussdb(dws )的分布式执行计划,并从计划中发现性能调节的优势。 前言执行计划或解释计划是数据库执行SQL语句的具体步骤。 例如,可以通过索引或扫描所有表来访问表,以及连接查询的实现方式和连接顺序。 如果SQL语句的性能不够好,则需要首先检查执行计划。 本文主要介绍如何详细解读基于gaussdb(dws )的分布式执行计划,并从计划中发现性能调整的优势。
1、介绍执行运算符要阅读执行计划,首先要了解数据库执行运算符的概念。
重点介绍基于sharing nothing的分布式计划中最重要的算子——STREAM算子
三种类型的stream算子1 ) http://www.Sina.com/(n:1 ) -每个源节点将数据发送到目标节点
2 ) http://www.Sina.com/(n:n ) -每个源节点基于连接条件计算哈希值,基于重新计算的哈希值分布数据,并向相应的目标节点发送数据
3 ) http://www.Sina.com/(1:n ) -从一个源节点向n个目标节点发送数据
其中1 )主要用于CN和DN间的数据交换,2 )和3 )主要用于DN间的数据交换
2、EXPLAIN的用法SQL执行计划是显示执行一个SQL语句时的详细步骤的节点数。 每一步都是数据库运算符,也称为执行运算符。 可以使用explain命令显示优化程序为每个查询生成的具体执行计划。
Gather Stream
其中,optiON的COSTS和NODES的默认值为on,其他参数缺省为OFF。
Redistribute Stream
a ) EXPLAIN QUERY并不实际运行,而是指定为只打印计划,option的ANALYZE可以实际运行
b ) PERFORMANCE选项缺省启用所有选项,以显示所有执行信息。
c ) CPU/BUFFER/DETAIL选项依赖于ANALYZE,并且仅当ANALYZE处于ON状态时才可用。
d ) DETAIL选项用于控制输出,如果DETAIL为ON,则会显示每个DN上的特定执行信息。 关闭DATAIL后,将显示所有DN的摘要信息,即最大最小信息。
Broadcast StreamGaussDB提供了两种显示格式normal/pretty,用于设置和控制参数explain_perf_mode。 其中normal格式是默认显示格式。
normal格式如下。
pretty格式如下。
改进的显示格式、层次清晰且计划中包含plan node id,使配置文件更简单、更直接。
以前是show explain_perf_mode; 单击查看当前数据库中使用的视觉样式。
同时设置set explain _ perf _ mode=pretty/normal; 来设置输出格式。
3、样本计划解读(每个运营商资源消耗、耗时等)1) EXPLAIN的语法建表文:
说明:
如果两个表是JOIN,且连接条件是每个表的分布列,并且关闭了流操作符,则CN会直接将语句发送到每个DN并执行,结果将由CN汇总。
2) EXPLAIN显示格式
如果两个表都已连接,并且连接条件包含非分布式列,则CN会在关闭流操作符的情况下向每个DN发出基表的扫描语句以在CN上连接。
1) 四中常见类型计划
每个DN不需要数据交换,因为两个表都是JOIN,且连接条件是每个表的分布式列。 CN在生成stream方案后,除去a) FQS计划,完全下推,下发query的方案发送给DN运行,在各个DN上进行基本表扫描,进行散列连接后发送给CN。
b) 非FQS计划,部分语句下推
如果两个表JOIN且连接条件都包含非分布式列,并且打开了流操作符,则会生成流计划,并且DN之间存在数据交换。 在此情况下,tt02表在各个DN中进行基本表扫描,扫描后通过c) Stream计划,DN之间无数据交换算子,根据JOIN条件的tt02.c1进行散列计算,然后重新发送至各个DN
Gather Stream
nce详解a) 执行计划
•id:执行算子节点编号。
•operation:具体的执行节点算子名称。
•A-time:各DN相应算子执行时间,[]中左侧为最小值,右侧为最大值,包括下层算子执行时间。
•A-rows:相应算子输出的全局总行数。
•E-rows:每个算子估算的输出行数。
•Peak Memory:各DN相应算子消耗内存峰值,[]中左侧为最小值,右侧为最大值。
•E-memory:DN上每个算子估算的内存使用量,只有DN上执行的算子会显示。某些场景会在估算的内存使用量后使用括号显示该算子在内存源充足下可以自动扩展的内存上限。
•E-width:每个算子输出元组的估算宽度。
•E-costs:每个算子估算的执行代价。
b) 谓词过滤
显示对应执行算子节点的过滤条件
c) 内存使用
主要显示CN的最大内存用量、DN最大内存用量、各算子的最大内存用量、各算子预估内存用量、Stream线程的启动以及收发时间。
d) Targetlist Information
各个算子对应的输出目标列信息。
e) DN信息
各算子的执行时间、Buffer、CPU信息
f) 自定义信息
CN与DN之间的建连信息、DN与DN之间的建连信息。
g) 汇总信息
DN执行器开始时间,[min_node_name, max_node_name] : [min_time, max_time]DN执行器结束时间,[min_node_name, max_node_name] : [min_time, max_time]Remote query poll time:接收结果时用于poll等待的时间CN执行器开始、运行及结束时间网络流量,stream算子发送的数据量优化器执行期时间查询ID总执行时间h) 执行时间介绍
每个算子的执行信息都包含三个部分:
其中:
dn_6001_6002/dn_6003_6004 表示具体执行的节点信息,括号中的信息是实际的执行信息actual time=0.013..2290.971 表示实际的执行时间第一个数字表示执行时进入当前算子到输出第一条数据所花费的时间
第二个数字为输出所有数据的总执行时间
注意:在整个计划中,除了叶子节点的执行时间是算子本身的执行时间,其余算子的执行时间均包含子节点的执行时间。
在该计划中,7号节点和9号节点为叶子节点,其余节点均为非叶子简介。1号节点时顶层节点,所以该节点的执行时间就可以作为整个查询的执行时间。
rows=2001550 表示当前算子输出数据为2001550行;loops=1 表示当前算子的只执行了一次,而对于分区表的扫描(7号节点)来说:该层扫描算子的loops为7,对于分区表,每一个分区表的扫描就是一次完整的扫描操作,当切换到下一个分区的时候,又是一次新的查询操作,查询该表定义如下:
Inventory表有7个分区,所以就执行了7次表扫描操作,因此loops=7。
i) CPU信息介绍
每个算子执行的过程都有CPU信息,其中cyc代表的是CPU的周期数,ex cyc表示的是当前算子的周期数,不包含其子节点;inc cyc是包含子节点的周期数;ex row是当前算子输出的数据行数;ex c/r则是ex cyc/ex row得到的每条数据所用的平均周期数。
j) Buffer信息介绍
buffers显示缓冲区信息,包括共享块和临时块的读和写。
共享块包含表和索引,临时块在排序和物化中使用的磁盘块。上层节点显示出来的块数据包含了其所有子节点使用的块数。
Buffers涉及的参数有两种,分别为:shared和temp,及shared hit/read/dirtied/written以及temp read/write
Hit blocks:代表从磁盘里面读到的数据块数
Dirtied blocks:代表当前查询中被修改了的并且此前未被修改的数据块数
Written blocks:代表当前线程将shared bufer里被修改的数据写回到磁盘的块数
k) 执行内存
其中:
Peak Memory:5KB 表示当前算子实际执行时使用的峰值内存;
Estimate Memory:1024MB 表示预估的内存,为优化器给出的预估值。
l) 其他执行信息
(1)sort 算子,会显示排序信息
Sort Method代表排序的方法,包括quicksort(快排)和disksort(外排)。快排即内存够用时,所有的排序操作均在内存中完成,外排说明当前可用内存不足,需要下盘。
(2)hashjoin算子
Buckets:代表hash表中实际使用的桶的个数
Batches:代表hashjoin中实际分块的数量。如果Batches=1,则说明所有的数据全在内存中,没有下盘操作;反之则说明有下盘操作,Batches - 1代表临时文件的个数。
Memory Usage:就是hashjoin中内存的使用情况
(3)hashagg算子
如果发生数据下盘,会有File Num:512信息,显示临时文件的个数。
(4)stream算子
stream算子的会统计当前算子处理数据的字节数,其从子线程获取数据的时间(poll time)以及处理数据的时间(Deserialize Time)。
stream算子的子节点会统计发送端的时间信息,如下:
发送时间Send time,排队时间Wait Quota time, OS发送时间以及数据处理的时间。
3) explain 调优示例一个查询语句要经过多个算子步骤才会输出最终的结果。由于个别算子耗时过长导致整体查询性能下降的情况比较常见。这些算子是整个查询的瓶颈算子。通用的优化手段是EXPLAIN ANALYZE/PERFORMANCE命令查看执行过程的瓶颈算子,然后进行针对性优化。
基表扫描时,对于点查或者范围扫描等过滤大量数据的查询,如果使用SeqScan全表扫描会比较耗时,可以在条件列上建立索引选择IndexScan进行索引扫描提升扫描效率。如下示例:
上述例子中,全表扫描返回3360条数据,过滤掉大量数据,在sssolddate_sk列上建立索引后,使用IndexScan扫描效率显著提高,从960毫秒提升到8毫秒。
结语:在调优过程中,熟练使用explain并能分析各部分数据结果是非常重要的。本文中仅仅介绍了大多数字段的含义以及根据explain结果进行调优的一个小示例,还可以与plan hint结合使用找出执行的最佳路径,也可以定位倾斜程度等等。
点击关注,第一时间了解华为云新鲜技术~