梁铭图,新炬网络首席架构师。具有十余年数据库运维、数据库设计、数据治理以及系统规划建设经验,拥有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.DMPlogfile=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信息加载至中间表
BEGINDBMS_SQLTUNE.CREATE_STGTAB_SQLSET('TAB_SQLSET', 'SPA', 'USERS');END;/BEGINDBMS_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 asselect * from spa.TAB_SQLSET@spa_link;
对目标端中间表进行处理,删除重复数据:
delete from spa.TAB_TARGET_SQLSET_20190918where rowid not in (select max(rowid)from spa.TAB_TARGET_SQLSET_20190918group by FORCE_MATCHING_SIGNATURE)and FORCE_MATCHING_SIGNATURE <> 0;COMMIT;
中间表数据关联到目标端SQL SET
目标端建立SQL SET
BEGINDBMS_SQLTUNE.CREATE_SQLSET(SQLSET_NAME => ' SQLSET_20190918_TEST',DESCRIPTION => 'SQL Set',SQLSET_OWNER => 'SPA');END;/
进行关联
BEGINDBMS_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
declarecur number := sys.DBMS_SYS_SQL.open_cursor;rc number;CURSOR cur_sql ISSELECT b.user_id,a.owner,a.object_name,'drop database link ' || object_name exec_sqlfrom dba_objects ainner join dba_users bon (a.owner = b.username)where object_type = 'DATABASE LINK';beginfor i in cur_sql loopSYS.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账户
declarel_a varchar2(30);beginl_a := DBMS_SQLPA.CREATE_ANALYSIS_TASK(sqlset_name => 'SQLSET_20190918_TEST',task_name => 'TASK_20190918',SQLSET_OWNER => 'SPA');end;/
源端目标端生成trail文件
源端
beginDBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name => 'TASK_20190918',execution_type => 'CONVERT SQLSET',execution_name => 'SOURCE_CONVERT_SQLSET');end;/
目标端
首先设置执行超过一分钟(生产环境可以按照实际情况酌情增加超时时间)的sql被kill掉:
beginDBMS_SQLPA.SET_ANALYSIS_TASK_PARAMETER(task_name => 'TASK_20190918',parameter => 'LOCAL_TIME_LIMIT',value => 60);end;/
为目标端生成trail文件,该操作会在目标端实际执行SQL,因此比较慢:
beginDBMS_SQLPA.EXECUTE_ANALYSIS_TASK(task_name => 'TASK_20190918',execution_type => 'TEST EXECUTE',execution_name => 'TARGET_EXEC');end;/
执行比较
比较执行时间
beginDBMS_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
beginDBMS_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;/
比较逻辑读
beginDBMS_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/oracleset trimspool onset trim onset pages 0set long 999999999set linesize 1000spool spa_report_elapsed_time.htmlSELECT 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.htmlSELECT 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.htmlSELECT 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.htmlSELECT dbms_sqlpa.report_analysis_task('TASK_20190918','HTML','errors','summary')FROM dual;spool off;spool spa_report_unsupport.htmlSELECT 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