SQL性能问题信息收集方法
一、总览
Sql语句性能问题需收集以下几类信息:
1、问题诊断过程及现场情况描述
2、sql语句文本
3、Sql语句当前执行时间
4、Sql语句当前执行计划
5、Sql语句中使用到的表、索引、函数、涉及的触发器、dblink等object的ddl,以及索引状态信息。
6、sql语句中使用到的主要表总行数、主要涉及字段直方图
7、Sql语句中主要子查询(如有)执行情况
8、Dmini参数
9、ET数据
收集后将上述信息粘贴到一个txt文件内,命名为“项目年月日***业务sql-N”不同sql分为不同文件保存。
请尽可能采集文本格式信息,如果因客户特殊要求也可以使用图片形式。

二、收集方法
2.1、问题初步诊断及问题描述
请现场同事对问题进行初步诊断分析,分析点包括但不限于以下方面:
1、sql性能问题是否是全表扫描造成
2、Sql性能问题是否与并发压力有关,在多少并发压力下出现
3、Sql性能问题是否和发起程序有关,如在应用程序中缓慢但在manager中执行正常
4、Sql涉及的表、索引是否有明显问题,如表上缺少索引等
5、Sql涉及的表、索引的统计信息是否准确
请收集以上信息进行并初步诊断,总结成对现场问题的详细描述及诊断过程粘贴到文档中。

2.2、sql语句文本
将sql全文本粘贴,如果sql使用了绑定变量,提供一组执行速度最慢的参数。

2.3、sql执行时间
在manager或disql中执行sql粘贴执行时间。

2.4、sql语句当前执行计划
在disql中执行以下命令:

call sf_set_session_para_value(‘ENABLE_MONITOR’,1)
 call sf_set_session_para_value(‘MONITOR_SQL_EXEC’,1)
 call sf_set_session_para_value(‘MONITOR_TIME’,1)
 set autotrace trace


然后执行sql语句,显示的执行计划中出现下图中的箭头,表示采集成功:

2.5、Sql语句中使用到的表、索引、函数、涉及的触发器、dblink等object的ddl
使用manager或disql生成表、索引、函数、涉及的触发器、dblink等object的ddl语句,对dblink、触发器等对象进行简单说明(用途等)。
检查相关索引的状态:
SELECT a.owner,a.index_name,a.visibility,a.status FROM ALL_INDEXES a;

2.6、主要表总行数及涉及字段直方图
使用Select count(1) from tablename;类似sql采集表总行数
使用 select 字段名,count(1) from tablename group by字段名 order by count(1);采集单列直方图信息。
使用select 字段名1,字段名2,…字段名n,count(1) from tablename group by 字段名1,字段名2,…字段名n order by count(1);采集多维直方图信息。

需要采集哪些字段的直方图信息,依据sql中使用了哪些字段做筛选,例如:select
***** from table1 where col1=**** and col2 =**** and col3 >*** 这种情况需要采集col1和col2的符合直方图(因为col3是不等值)
同时需要采集去掉范围筛选后的返回行数:
例如如下sql:
Select ***** from table1 where col1=**** and col2 =**** and col3 >
需要采集以下sql:
Select Count(1) from table1 where col1=
* and col2 =**** ;

2.7、主要子查询执行情况
将sql中子查询使用count(1)采集返回行数和执行时间,相关子查询改写为非相关子查询执行,例如以下sql:

SELECT
 count(0)
 FROM
 (
 SELECT
 *
 FROM
 (
 SELECT DISTINCT
 aa.id AS id ,
 aa.ENTERPRISE_ID AS enterpriseId ,
 aa.ENTERPRISE_NAME AS enterpriseName ,
 aa.table1_MODEL AS table1Model ,
 aa.table1_NAME AS table1Name ,
 aa.table1_TRADEMARK_NAME AS table1Trademark,
 aa.DIRECTORY_NUMBER AS directoryNumber ,
 aa.VEHICLE_SERIAL_NUMBER
 FROM
 cq_table1_basic_t aa
 WHERE
 aa.del_flag = ‘0’
 and exists (
 select 1 from cq_table1_apply_t x
 WHERE
 x.del_flag = ‘0’
 AND x.apply_status = ‘storage’
 AND aa.id = x.table1_id
 )
)
            
            UNION ALL
            
            SELECT
                    a.id                     AS id              ,
                    a.ENTERPRISE_ID          AS enterpriseId    ,
                    a.ENTERPRISE_NAME        AS enterpriseName  ,
                    a.table1_MODEL          AS table1Model    ,
                    a.table1_NAME           AS table1Name     ,
                    a.table1_TRADEMARK_NAME AS table1Trademark,
                    a.DIRECTORY_NUMBER       AS directoryNumber ,
                    a.VEHICLE_SERIAL_NUMBER
            FROM
                    cq_table1_history_basic_t a
            WHERE
                    a.del_flag = '0'
               AND NOT EXISTS
                    (
                            SELECT id FROM cq_table1_basic_t t WHERE t.id = a.id
                    )
                AND EXISTS
                    (
                            SELECT
                                    1
                            FROM
                                    cq_table1_history_apply_t b
                            WHERE
                                    a.id           = b.table1_id
                                AND b.del_flag     = '0'
                                AND b.apply_status = 'storage'
                    )
    )

这个sql的主体结构是由union all连接的两个部分组成,需要分别执行union all上下两个子查询并记录时间。
其中红色的子查询部分,改写成:

SELECT
 Count(1) --记录行数
 FROM
 cq_table1_history_apply_t b
 WHERE
 /* a.id = b.table1_id
 AND */ --去掉与主查询关联部分
 b.del_flag = ‘0’
 AND b.apply_status = ‘storage’

并记录执行时间。

2.9、dmini参数

2.10、ET数据
在manager中执行

SP_SET_PARA_VALUE(1,‘ENABLE_MONITOR’,1);
 SP_SET_PARA_VALUE(1,‘MONITOR_TIME’,1);
 SF_SET_SESSION_PARA_VALUE(‘MONITOR_SQL_EXEC’,1);


然后执行sql语句,获取执行号

再执行
ET(执行号)–如果一次执行没有结果,需要多尝试几次