1什么是火焰图
后端开发人员大多知道一种叫做火焰图(Flame Graph)的工具,这是一款开发工程师常用的可视化的性能分析工具,由Linux性能优化大师Brendan Gregg发明,主要用于展示程序运行过程中的函数调用层次结构以及各个调用栈占用的时间比例,从而帮助开发者快速识别性能瓶颈。下面是MySQL数据库的一张火焰图

火焰图通过SVG格式的矢量图展示,它将函数调用栈的深度用纵向(Y轴)表示,每个函数占据一层;横向(X轴)表示函数的执行消耗(可以是时间、执行次数等),宽度越宽表示函数被调用的次数越多或执行时间越长。
2用火焰图分析执行计划
2.1 Oracle执行计划和程序运行的相似性
Oracle执行计划和程序运行有一定的相似性,这里用一个简单的C程序说明一下,一个简单的C程序从一个main()开始,这个函数调用一个do_something(),这个do_something()在调用一个get_item()取得它所需要的,在执行一些其它的操作,然后返回到main()函数。一个语句的执行计划也有着相似的过程,比如下面执行执行计划
------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | Pstart| Pstop |
------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 3844 (100)| | | |
| 1 | HASH GROUP BY | | 238 | 16422 | 3844 (1)| 00:00:01 | | |
|* 2 | HASH JOIN | | 255 | 17595 | 3843 (1)| 00:00:01 | | |
| 3 | TABLE ACCESS FULL | PRODUCTS | 72 | 2088 | 2 (0)| 00:00:01 | | |
| 4 | VIEW | VW_GBC_5 | 255 | 10200 | 3841 (1)| 00:00:01 | | |
| 5 | HASH GROUP BY | | 255 | 7140 | 3841 (1)| 00:00:01 | | |
|* 6 | HASH JOIN RIGHT OUTER| | 918K| 24M| 3825 (1)| 00:00:01 | | |
| 7 | TABLE ACCESS FULL | CHANNELS | 5 | 65 | 2 (0)| 00:00:01 | | |
| 8 | PARTITION RANGE ALL | | 918K| 13M| 3821 (1)| 00:00:01 | 1 | 15 |
| 9 | TABLE ACCESS FULL | SALES | 918K| 13M| 3821 (1)| 00:00:01 | 1 | 15 |
------------------------------------------------------------------------------------------------------
执行计划的入口是是id为0的SELECT STATEMENT,SELECT STATEMENT调用HASH GROUP BY,HASH GROUP BY调用HASH JOIN,依次类推,一直到最深层的操作,然后依次返回。
2.2 为什么要用火焰图分析SQL执行计划
上一节的执行计划还不算复杂,只有9个操作,不借助可视化工具,分析起来还比较容易,很快就能找到执行最长的操作是最后的全表扫描,有些业务系统的SQL就不这么容易看了,操作数十个甚至数百上千个,电脑上显示数页和数十页,一页一页翻起来很容易头晕眼花,不借助于可视化工具,属实有点棘手。Oracle页提供了类似的可视化工具,使用 Real-Time SQL Monitoring tool可以生成可视化的执行计划,可以
生成像下面执行计划

上面的图非常直观,也容易定位到执行时间长的操作,但是在执行计划很长的情况下,也需要翻页查找。如果借助火焰图来分析,就直观多了,请接着往下看。
3生成火焰图
3.1 下载SQL脚本
知名的数据库专家Tanel Põder(参与过)开发了一个SQL脚本,这个脚本放在github上,可以从下面的连接下载用来生成SQL火焰图
火焰图SQL脚本
下载后拷贝到火焰图的项目目录下
3.2 下载火焰图项目
火焰图的介绍和下载地址连接如下
火焰图项目地址
下载后也放到Oracle用户home目录下
3.3 设置数据库参数
SQL火焰图这个脚本依赖V$SQL_PLAN_STATISTICS_ALL,因此需要在statistics_level=all的情况下运行语句,也可以在执行语句时使用 GATHER_PLAN_STATISTICS hint
alter system set statistics_level=‘all’ scope=both;
3.4 简单SQL语句的火焰图
使用SQL plus登陆数据前先切换到火焰图的项目目录下
--查询要分析语句的SQL_ID和子游标号
SQL_ID CHILD_NUMBER SQL_TEXT
------------- ------------ ----------------------------------------------------------------
0fzaj7fn59nv3 0 SELECT p.PROD_CATEGORY,p.PROD_SUBCATEGORY,c.CHANNEL_DESC,sum(s.Q
INNERLES s UANTITY_SOLD), sum(s.AMOUNT_SOLD)
LEFT JOIN CHANNE JOIN PRODUCTS p ON p.PROD_ID=s.PROD_ID
GROUP BY p.PROD_CATEGORYS c ON c.CHANNEL_ID =s.CHANNEL_ID
,p.PROD_SUBCATEGORY,c.CHANNEL_DESC
--运行火焰图SQL脚本
@sql_flame.sql 0fzaj7fn59nv3 0
用浏览器打开生成的svg图片

看一下这个执行计划的火焰图,无论这个执行计划有长,火焰图总是在一屏内显示(执行计划的深度比较应用程序调用栈的深度来说,应该是浅多了),操作之间的调用关系一眼看出,从图上可以很容易看到一个操作所在的层次,通过它的宽度也很容易发现一个层次中执行时间最长的操作,也可以从宽度来判断它的执行时间在这个层次的执行占比。点击一个操作,可以显示详细的信息。

鼠标移动到id为9的操作上,可以看到这个操作的详细信息,执行时间及执行时间占总时间的比例。
5 一个复杂SQL语句的例子
下面的火焰图来自Tanel Põder的博客,从这个例子可以感受一下复杂sql语句的火焰图

6 后记
火焰图不仅可以分析Oracle数据库的SQL执行计划,也可以分析Postgresql数据库的执行计划,原理上,只要一个数据库的执行计划包含度量信息(时间、io,cpu)就可以使用火焰图来分析。
相对于dba来说,开发可能对这个火焰图更容易上手,毕竟他们在做其他性能分析时已经使用过了。




