梁铭图,新炬网络首席架构师。具有十余年数据库运维、数据库设计、数据治理以及系统规划建设经验,拥有Oracle OCM和ACE Director、Togaf企业架构师(鉴定级)、IBM CATE等认证,曾获dbaplus年度MVP、华为云MVP等荣誉,并参与数据资产管理国家标准的编写工作。在数据库运维管理和架构设计、运维体系规划、数据资产管理方面有深入研究。
背景
迁移数据库或者升级数据库前后,目标数据库可能因为版本、补丁或者其他不可预知的原因造成数据库性能急剧衰退。为避免应用启动上线后,我们才手忙脚乱地做出被动的优化后应,我们需要在数据库正式迁移或升级前使用ORACLE 的SPA(SQL Performance Analyzer)综合评估原库的SQL在目标库执行时没有出现性能衰退。SPA通过比较原库和目标库收集的SQL集合的执行统计数据,最终给我们一个比较结果,通过分析对比结果数据可明确哪些SQL出现性能衰退。查找衰退原因修复问题,确保SQL在迁移后能满足业务需求。
SQL性能分析器概要
使用SPA工具可以准确地评估更改对组成工作量的 SQL 语句的影响。SQL 性能分析器可帮助预测潜在的更改对 SQL 查询工作量的性能影响。这种功能可向 DBA 提供有关 SQL 语句性能的详细信息,例如,执行前后的统计信息,提高或降低性能的语句。这样一来,您就可以执行诸如以下操作的操作:在测试环境中进行更改,以确定数据库升级是否会改进工作量性能,使用情景比如数据库升级、实施优化建议、更改方案、收集统计信息、更改数据库参数、更改操作系统和硬件等等。
其过程可分为以下几个主要步骤:
收集 SQL:在这个阶段中,将收集用于表示生产系统中的 SQL 工作量的 SQL 语句集。可以使用 SQL 优化集或自动工作量资料档案库 (AWR) 来捕获要传送的信息。因为 AWR 本质上是捕获高负载的 SQL,所以应考虑修改默认的 AWR 快照设置和捕获的顶级 SQL,以确保 AWR 捕获最大数量的 SQL 语句。这可以确保捕获更加完整的 SQL 工作量。
传送:在这个阶段中,应将得到的工作量结果传送到测试系统。从生产系统导出 STS,然后将 STS 导入到测试系统。
计算“之前版本”性能:在进行任何更改之前,执行 SQL 语句,收集评估将来的更改对工作量性能的可能影响所需的基线信息。在此阶段收集的信息给出了系统工作量当前状态的一个快照。性能数据包括:执行计划(如由解释计划生成的计划)和执行统计信息(如由占用时间、缓冲获取次数、磁盘读取次数和已处理的行数组成的信息)
进行更改:获得了之前版本数据后,可以实施计划的更改,然后开始查看对性能的影响。
计算“之后版本”性能:在数据库环境中进行了更改之后才执行此步骤。SQL 工作量的每个语句都在虚拟执行(仅收集统计信息)模式下运行,收集与步骤 3 所捕获的信息相同的信息。
比较和分析 SQL 性能:在获得了两个版本的 SQL 工作量性能数据后,可以通过比较之后版本与之前版本的数据来进行性能分析。比较的根据是执行统计信息,如所用时间、CPU 时间和缓冲区获取次数等。
优化回归的 SQL:在此阶段中,已经准确地确认了哪些 SQL 语句在进行数据库更改时可能导致性能问题。在此阶段中可以使用任何一种数据库工具来优化系统。例如,可以对确认的语句使用 SQL 优化指导或访问指导,然后实施相应的建议。也可以使用在步骤 3 中捕获的计划植入 SQL 计划管理 (SPM) 以确保计划保持不变。在实施了任何优化操作后,应重复该过程来创建新的之后版本,然后分析性能差异以确保新的性能是可接受的。
实施过程
1)准备工作
测试环境原库为11.2.0.4,目标库同为11.2.0.4,向目标库迁移一个test表空间,在目标库中建立spa-sts,首先通过dblink在原库执行sql trial,然后在目标库执行SQL trial,最后比较两个SQL trial。这样就达到了对比迁移后SQL有无性能衰退情况。
源端:
环境准备:创建SPA测试专用用户
采集数据(在生产库转化AWR中SQL为SQL Tuning Set,在生产库从现有SQL Tuning Set提取SQL)
导出数据:打包(pack)转化后的SQL Tuning Set,并导出传输到测试服务器
源端目标端分别建立SPA用户
CREATE USER SPA IDENTIFIED BY oracle;
GRANT DBA TO SPA;
源端业务账号迁移至目标端
源端导出:
expdp \'/ as sysdba\' dumpfile=SCOTT.dmp directory=MYDUMP
schemas=SCOTT logfile=scott.log cluster=no
目标端:
环境准备:创建SPA测试专用用户
测试准备:导入SQL Tuning Set表,并解包(unpack),创建SPA分析任务
前期性能:从SQL Tuning Set中转化得出11g的性能Trail
后期性能:在19c测试数据库中执行SQL Tuning Set中SQL,生成19c性能Trail
对比分析:执行对比分析任务,分别按执行时间,CPU时间和逻辑读三个维度进行
汇总报告:取出对比报告,对每个维度分别取出All,Unsupport,Error 3类报告
总结报告:分析汇总报告,优化其中的性能下降SQL,编写SPA测试报告
目标端导入:
impdp \'/ as sysdba\' directory=DATA_PUMP_DIR dumpfile=SCOTT.DMP
logfile=SCOTT.log cluster=no
建立dblink方便传输SQLSET
create database link spa_link connect to spa identified by oracle using 'SOURCEDB';
源端建立SQLSET
源端AWR中的SQL载入到SQL SET(尽可能多的捕捉SQL)
查询snap_id
将SQL加载至SQL SET
查看SQL SET信息
将SQL SET 中的SQL信息加载至中间表
BEGIN
DBMS_SQLTUNE.CREATE_STGTAB_SQLSET('TAB_SQLSET', 'SPA', 'USERS');
END;
/
BEGIN
DBMS_SQLTUNE.PACK_STGTAB_SQLSET(SQLSET_NAME => 'SQLSET_20190918_TEST',
SQLSET_OWNER => 'SPA',
STAGING_TABLE_NAME => 'TAB_SQLSET',
STAGING_SCHEMA_OWNER => 'SPA');
END;
/
将源端的SQL SET 表导入至目标端
目标端进行抽取
create table spa.TAB_TARGET_SQLSET_20190918 as
select * from spa.TAB_SQLSET@spa_link;
对目标端中间表进行处理,删除重复数据:
delete from spa.TAB_TARGET_SQLSET_20190918
where rowid not in (select max(rowid)
from spa.TAB_TARGET_SQLSET_20190918
group by FORCE_MATCHING_SIGNATURE)
and FORCE_MATCHING_SIGNATURE <> 0;
COMMIT;
中间表数据关联到目标端SQL SET
目标端建立SQL SET
BEGIN
DBMS_SQLTUNE.CREATE_SQLSET(SQLSET_NAME => ' SQLSET_20190918_TEST',
DESCRIPTION => 'SQL Set',
SQLSET_OWNER => 'SPA');
END;
/
进行关联
BEGIN
DBMS_SQLTUNE.Unpack_Stgtab_Sqlset(sqlset_name => 'SQLSET_20190918_TEST',
sqlset_owner => 'SPA',
replace => TRUE,
staging_table_name => 'TAB_TARGET_SQLSET_20190918',
staging_schema_owner => 'SPA');
END;
/
目标端删除DBLINK
declare
cur number := sys.DBMS_SYS_SQL.open_cursor;
rc number;
CURSOR cur_sql IS
SELECT b.user_id,
a.owner,
a.object_name,
'drop database link ' || object_name exec_sql
from dba_objects a
inner join dba_users b
on (a.owner = b.username)
where object_type = 'DATABASE LINK';
begin
for i in cur_sql loop
SYS.DBMS_SYS_SQL.parse_as_user(c => cur,
statement => i.exec_sql,
language_flag => DBMS_SQL.native,
userID => i.user_id);
rc := SYS.DBMS_SYS_SQL.execute(cur);
end loop;
SYS.DBMS_SYS_SQL.close_cursor(cur);
end;
/
检查:
目标端建立TASK
连接到SPA账户
declare
l_a varchar2(30);
begin
l_a := DBMS_SQLPA.CREATE_ANALYSIS_TASK(sqlset_name => 'SQLSET_20190918_TEST',
task_name => 'TASK_20190918',
SQLSET_OWNER => 'SPA');
end;
/
源端目标端生成trail文件
源端
begin
DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name => 'TASK_20190918',
execution_type => 'CONVERT SQLSET',
execution_name => 'SOURCE_CONVERT_SQLSET');
end;
/
目标端
首先设置执行超过一分钟(生产环境可以按照实际情况酌情增加超时时间)的sql被kill掉:
begin
DBMS_SQLPA.SET_ANALYSIS_TASK_PARAMETER(task_name => 'TASK_20190918',
parameter => 'LOCAL_TIME_LIMIT',
value => 60);
end;
/
为目标端生成trail文件,该操作会在目标端实际执行SQL,因此比较慢:
begin
DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name => 'TASK_20190918',
execution_type => 'TEST EXECUTE',
execution_name => 'TARGET_EXEC');
end;
/
执行比较
比较执行时间
begin
DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name => 'TASK_20190918',
execution_type => 'COMPARE PERFORMANCE',
execution_name => 'Compare_elapsed_time',
execution_params => dbms_advisor.arglist('execution_name1','SOURCE_CONVERT_SQLSET','execution_name2','TARGET_EXEC','comparison_metric','elapsed_time'));
end;
/
比较CPU
begin
DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name => 'TASK_20190918',
execution_type => 'COMPARE PERFORMANCE',
execution_name => 'Compare_CPU_time',
execution_params => dbms_advisor.arglist('execution_name1', 'SOURCE_CONVERT_SQLSET','execution_name2','TARGET_EXEC','comparison_metric','CPU_TIME'));
end;
/
比较逻辑读
begin
DBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name => 'TASK_20190918',
execution_type => 'COMPARE PERFORMANCE',
execution_name => 'Compare_BUFFER_GETS_time',
execution_params => dbms_advisor.arglist('execution_name1','SOURCE_CONVERT_SQLSET','execution_name2','TARGET_EXEC','comparison_metric','BUFFER_GETS'));
end;
/
查看报告
conn spa/oracle
set trimspool on
set trim on
set pages 0
set long 999999999
set linesize 1000
spool spa_report_elapsed_time.html
SELECT dbms_sqlpa.report_analysis_task('TASK_20190918',
'HTML',
'ALL',
'ALL',
top_sql => 1000,
execution_name => 'Compare_elapsed_time')
FROM dual;
spool off;
spool spa_report_CPU_time.html
SELECT dbms_sqlpa.report_analysis_task('TASK_20190918',
'HTML',
'ALL',
'ALL',
top_sql => 1000,
execution_name => 'Compare_CPU_time')
FROM dual;
spool off;
spool spa_report_buffer_time.html
SELECT dbms_sqlpa.report_analysis_task('TASK_20190918',
'HTML',
'ALL',
'ALL',
top_sql => 1000,
execution_name => 'Compare_BUFFER_GETS_time')
FROM dual;
spool off;
spool spa_report_errors.html
SELECT dbms_sqlpa.report_analysis_task('TASK_20190918',
'HTML',
'errors',
'summary')
FROM dual;
spool off;
spool spa_report_unsupport.html
SELECT dbms_sqlpa.report_analysis_task('TASK_20190918',
'HTML',
'unsupported',
'all')
FROM dual;
spool off;
/
报告中详细说明总共分析SQL数量,不支持SQL,得到性能改善,没有变化的SQL的具体数量。
以及总体性能改善了百分比
以及得到明显改善的SQL
我们还可以通过errors.html可看到执行失败的语句原因分析以及通过unsupport.html可看到不支持的SQL原因分析。
小结
目前,SPA评估是我们实施数据库迁移和升级项目中一个必备的步骤。它可以协助我们及时提前在数据库迁移正式上线前,发现、分析和优化可能会遇到的各种性能问题,为项目的成功实施起到关键作用。
如果字段的最大可能长度超过255字节,那么长度值可能…
只能说作者太用心了,优秀
感谢详解
一般干个7-8年(即30岁左右),能做到年入40w-50w;有…
230721