关键字:
SQL、执行计划
什么是执行计划
(1)执行计划用于描述SQL语句在数据库中的执行过程,常用语SQL性能分析。
(2)执行计划是数据库查询优化器选择出来的执行语句的方案。
(3)执行计划依赖于准确的数据库统计信息,包含系统统计信息和对象统计信息。
(4)KES使用的是基于代价(cost)的执行计划,它是优化器对于该语句要运行多久的预估。
(5)执行计划会显示启动代价和总代价,对于大部分查询来讲总代价是最需要被关注的。
执行计划查看方式
执计计划可以通过如下的方式进行查看:
(1)通过explain命令查看
(2)通过对象管理工具查看
2.1.1 explain的主要选项
选项 | 默认值 | 功能说明 |
analyze | false | 执行命令并显示执行事件 |
verbose | false | 显示附加信息,比如计划树中每个节点输出的字段名等 |
costs | true | 显示执行计划的成本 |
buffers | false | 显示缓冲区的使用信息,包括共享快、本地块和临时读写块,前置条件是analyze |
format | text | 指定执行计划的输出格式,支持:TEXT、XML、JSON或者YAML |
timing | true | 在输出中包括实际启动时间以及每个节点中花掉的时间,前置条件是analyze |
2.1.2 查看预估成本
kops=# explain SELECT * FROM public.km_inspect_job; QUERY PLAN ------------------------------------------------------------------ Seq Scan on km_inspect_job (cost=0.00..10.70 rows=70 width=998) (1 行记录) |
等价于:
kops=# explain (costs) SELECT * FROM public.km_inspect_job; QUERY PLAN ------------------------------------------------------------------ Seq Scan on km_inspect_job (cost=0.00..10.70 rows=70 width=998) (1 行记录) |
(1)0.00表示估计启动开销
(2)10.70是总的消耗
(3)rows=70是预测的行数,与实际的行数可能有出入
(4) Seq Scan表示运算类型,一些常见的可选项:
1、顺序扫描(Seq scan):根据实际的数据的存取顺序,连续的扫描所有数据。适用于数据量比较少的表,比如1000条以下;选择率比较高的数据,比如50%以上都选择出来了。
2、索引扫描(Index scan):根据所建的索引,根据查询过滤条件扫描索引,因为索引是有序的,所以采用的折半查找,可以快速的找到符合条件的索引数据,然后过滤条件和索引键值进行比较,符合条件的索引项,根据索引项记录的实际数据存储位置读取数据,然后根据过滤条件进行过滤。适用于数据量比较大的而且选择比较少的,比如10000条以上记录,选择率在1-20%的。
3、位图扫描(Bitmap scan):bitmap扫描是Bitmap Index Scan和Bitmap Heap Scan的组合。先通过Bitmap Index Scan索引扫描,在内存中创建一个位图表,每一个bit表示一个与过滤条件有关的页面。此页面有可能有数据为1,不可能为0。然后再通过Bitmap Heap Scan表扫描, 在内存中创建好的位图表指针对应的页面进行顺序扫描,排除不符合的记录,返回需要的结果。适用于列中有重复值,查询中包含 and、or 等范围查找的情况,其中对于有多个条件的组合(AND、OR),可以分别对每个条件做Bitmap Index Scan,然后再对结果进行AND或OR操作或当列中的数值散乱在内存中,用于整理数值。
4、TID扫描(TID scan):根据数据实际存储位置的ctid进行扫描,获取元组。通过隐藏字段ctid,扫描 ctid 是 KingbaseES 中标记数据位置的字段,通过这个字段来查找数据,速度非常快。适用于一般where条件带citd的。
5、覆盖索引扫描(Index only scan):允许直接从索引得到元组,覆盖索引扫描要求查询中的某个表所需要数据均可以从这个表上的同一个索引的索引页面中获得。适用于更新少的表。
6、嵌套循环连接(NestLoop join):扫描每一条外表的数据(m条数据),然后和内表所有的记录(n条数据)去连接,时间复杂度是o(mn)。适用于数据量不大的情况。
7、哈希连接(Hash join):对内表建立hash表,扫描所有内表数据到各个hash桶里面,建立hash桶,然后一行行扫描外表数据,对外表数据进行hash,hash到某个桶里面,然后跟这个桶里面的数据进行连接。适用于数据分布比较随机无序,重复值不是特别多的情况。
8、归并连接(Merge join):对两个表的数据进行排序,然后做连接。适用于两个表的数据都是基本有序。
9、排序节点(Sort):明确对数据进行排序。我们不可能完全消除明确的排序,但是把关闭这个选项可以让优化器在存在其它方法的时候优先选择其它方法。适用于输出结果是有序的的情况。
10、去重节点(Unique):Unique节点用于对下层节点返回的已排序元组进行去重操作。由于下层节点获取到的元组已经排序,因此在Unique节点的执行过程中只需要缓存上一个返回的元组,判断当前获f的元组是否和上一个元组在指定属性上重复。如果重复,则忽略当前元组并继续从下层节点获取元组;如果不重复,则输出当前元组并用它替换缓存中的元组。适用于Unique节点一般用于处理査询中的DISTINCT关键字,但这不是唯一的处理方式。如果要求去重的属性被“ORDER BY”子句引用时,一般会使用Unique节点进行处理。
2.1.3 查看实际执行语句
kops=# explain (analyze) SELECT * FROM public.km_inspect_job; QUERY PLAN ------------------------------------------------------------------------------------------------------------ Seq Scan on km_inspect_job (cost=0.00..10.70 rows=70 width=998) (actual time=0.014..0.017 rows=4 loops=1) Planning Time: 0.090 ms Execution Time: 0.042 ms (3 行记录) |
(1)actual time表示当前节点单次实际的启动时间和执行时间。
(2)Planning Time表示生成执行计划所需时间。
(3)Execution Time表示实际执行这条SQL语句花费时间,不包括生成执行计划的时间。
2.1.4 查看缓冲区命中情况
kops=# explain (analyze, buffers) SELECT * FROM public.km_inspect_job; QUERY PLAN ------------------------------------------------------------------------------------------------------------ Seq Scan on km_inspect_job (cost=0.00..3.76 rows=76 width=233) (actual time=1.013..1.485 rows=66 loops=1) Buffers: shared read=3 dirtied=2 Planning Time: 0.977 ms Execution Time: 1.542 ms (4 行记录) |
read=3:表示从磁盘中读了3块
dirtied=2:表示脏块有2个。
2.1.5 查看附加信息
kops=# explain (verbose) SELECT * FROM public.km_inspect_job; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------- Seq Scan on public.km_inspect_job (cost=0.00..3.76 rows=76 width=233) Output: id, config_id, config_type, name, inspect_time, exec_result, items, creator, create_time, updater, update_time, deleted, inspect_end_time (2 行记录) |
显示各个列的信息。
2.1.6 设置输出格式
输出为json:
kops=# explain (format json) SELECT * FROM public.km_inspect_job; QUERY PLAN ------------------------------------------ [ + { + "Plan": { + "Node Type": "Seq Scan", + "Parallel Aware": false, + "Relation Name": "km_inspect_job",+ "Alias": "km_inspect_job", + "Startup Cost": 0.00, + "Total Cost": 3.76, + "Plan Rows": 76, + "Plan Width": 233 + } + } + ] (1 行记录) |
输出为yaml:
kops=# explain (format yaml) SELECT * FROM public.km_inspect_job; QUERY PLAN ------------------------------------- - Plan: + Node Type: "Seq Scan" + Parallel Aware: false + Relation Name: "km_inspect_job"+ Alias: "km_inspect_job" + Startup Cost: 0.00 + Total Cost: 3.76 + Plan Rows: 76 + Plan Width: 233 (1 行记录) |
除了文本形式的执行计划查看方式,KingbaseES还支持通过“对象管理工具”以图形化的方式来查看和展现执行计划。
打开管理器,输入SQL,然后点击执行计划,就可以显示执行计划。
总结
本文主要介绍了如何来查看执行计划,着重介绍了通过explain命令来查看执行计划,和explain命令的的常用参数,以及执行结果的一些分析。