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(执行号)–如果一次执行没有结果,需要多尝试几次