Oracle SPA(SQL Performance Analyzer)实操
Oracle SPA(SQL Performance Analyzer)实操
本次SPA实操主要是基于redhat6.4+11.2.0.4的源端,目标端为win+19.3.0.0(11g到19c的SPA操作)
1、什么是SPA(SQL Performance Analyzer)?
SPA(SQL Performance Analyzer)是Oracle的SQL性能优化分析器。Oracle Database 11g 引入了 SQL 性能分析器;使用该工具可以准确地评估数据库变更对 SQL 语句的影响。SQL 性能分析器可帮助预测潜在的更改对 SQL 的性能影响。这种功能可向 DBA 提供有关 SQL 语句性能的详细信息,例如,执行前后的统计信息,提高或降低性能的语句。
SPA其实也是Oracle Real Application Testing的一个组件,另外一个组件Database Replay。SPA的原理是通过变更前对收集的STS进行执行,获取基线数据,变更后再次进行执行,然后进行对比,从多个维度比如CPU时间,I/O,buffer get等生成详细的变更对比报告。典型用法是捕捉STS,然后通过SPA生成对比报告,然后对变更后衰减的SQL调用STA进行优化。
2、SPA作用
SQL 性能分析器可用于预测和防止会影响 SQL 执行计划结构的任何数据库环境更改所带来的潜在性能问题。这些更改可以包括(但不限于)以下任何一种更改:
- 数据库升级
- 实施优化建议
- 更改方案
- 收集统计信息
- 更改数据库参数
- 更改操作系统和硬件
3、SPA测试流程
为了尽可能的减小对正式生产库的性能影响,SPA测试可以从AWR资料库中的SQL数据转化而来的SQL Tuning Set进行整体的SQL性能测试。
本次测试主要分为以下几个步骤:
在源端:
- 环境准备:创建SPA测试专用用户
- 采集数据:
a)在生产库转化AWR中SQL为SQL Tuning Set
b)在生产库从现有SQL Tuning Set提取SQL - 导出数据:打包(pack)转化后的SQL Tuning Set,并导出传输到测试服务器
在目标库端:
- 环境准备:创建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测试报告
4、SPA实操
4.1、初始化数据库(源端和目标端数据库)
在进行SPA操作前,需要为数据库进行检测,目标端的数据库的表空间的大小和名字需要和源端的表空间的大小和名字一致(除去系统表空间)
a、检测源端数据库的表空间
SQL> select tablespace_name,bytes/1024/1024m from dba_data_files;
TABLESPACE_NAME M
------------------------------ ----------
SYSTEM 700
SYSAUX 600
UNDOTBS1 200
USERS 5
TEST 100
b、查看目标端表空间
SQL> select tablespace_name,bytes/1024/1024m from dba_data_files;
TABLESPACE_NAME M
------------------------------ ----------
SYSTEM 900
SYSAUX 600
USERS 5
UNDOTBS1 55
通过对表空间的检测可以看到,目标端没有test表空间,需要在目标端创建一个名为TEST,大小为100 MB的表空间
c、目标端进行表空间创建
SQL> select file_name,tablespace_name from dba_data_files;
FILE_NAME TABLESPACE_NAME
-------------------------------------------------------------------------------- ------------------------------
C:\ORACLE\APP\LI\ORADATA\HAPPY\LUFFY\DATAFILE\O1_MF_SYSTEM_GJ3K66GF_.DBF SYSTEM
C:\ORACLE\APP\LI\ORADATA\HAPPY\LUFFY\DATAFILE\O1_MF_SYSAUX_GJ3K79OK_.DBF SYSAUX
C:\ORACLE\APP\LI\ORADATA\HAPPY\LUFFY\DATAFILE\TEST.DBF TEST
C:\ORACLE\APP\LI\ORADATA\HAPPY\LUFFY\DATAFILE\O1_MF_USERS_GJ3K7T1V_.DBF USERS
C:\ORACLE\APP\LI\ORADATA\HAPPY\LUFFY\DATAFILE\O1_MF_UNDOTBS1_GJ3K7RWQ_.DBF UNDOTBS1
4.2、导入导出数据
把源端的tns拷贝到目标端(测试不需要,如果是生产库则需要进行tns的拷贝)
同时需要注意DB link
a、源端导出数据
[oracle@source dump]$ ./full.sh
/oracle/app/oracle/product/11.2.0/dbhome_1/bin/expdp system/oracle DIRECTORY=dump_dir parallel=1 dumpfile=source_full_` date +%y%m%d`_%U.dmp logfile=source_full_` date +%y%m%d`.log compression=all cluster=N full=y
目标端导入数据
C:\Users\li>impdp ' / as sysdba' directory=dump parallel=1 dumpfile=source_full_190617_01.dmp logfile=impdp.source.full.log cluster=no full=y
4.3、源端与目标端进行SPA
4.3.1、源端操作
1、环境准备
创建SPA专用用户
create user spa identified by spa default tablespace users;
grant dba to spa;
grant advisor to spa;
grant select any dictionary to spa;
grant administer sql tuning set to spa;
2、采集数据
a)在生产库转化AWR中SQL为SQL Tuning Set
b)在生产库从现有SQL Tuning Set提取SQL
在生产端,使用Oracle SQL Tuning工具包,从AWR资料库数据中转化得到SQL Tuning Set,用于整个SPA测试流程中的SQL来源。
为了确保对生产环境影响最小,我们只对生产端采集AWR的SQL,具体采集步骤如下:
a、获取AWR快照的边界ID
set lines 188 pages 1000
col snap_time for a22
col min_id new_value minid
col max_id new_value maxid
select min(snap_id) min_id, max(snap_id) max_id
from dba_hist_snapshot
where end_interval_time > trunc(sysdate)-30
order by 1;
MIN_ID MAX_ID
---------- ----------
20 20
b、创建SQL Set
连接用户:
conn spa/spa
如果之前有这个SQLSET,可以这样删除:
EXEC DBMS_SQLTUNE.DROP_SQLSET (SQLSET_NAME => 'SOL_SQLSET_201906', SQLSET_OWNER => 'SPA');
新建SQLSET:SOL_SQLSET_201906
EXEC DBMS_SQLTUNE.CREATE_SQLSET (-
SQLSET_NAME => 'SOL_SQLSET_201906',-
DESCRIPTION => 'SQL Set Create at : '||TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'),-
SQLSET_OWNER => 'SPA');
查询sql set信息:
col DESCRIPTION for a50
select owner,name,STATEMENT_COUNT,DESCRIPTION,CREATED from dba_sqlset;
OWNER NAME STATEMENT_COUNT DESCRIPTION CREATED
------------------------------ ------------------------------ --------------- -------------------------------------------------- ---------
SPA SOL_SQLSET_201906 0 SQL Set Create at : 2019-06-17 23:57:05 17-JUN-19
c、转化AWR数据中的SQL数据,将其中的SQL载入到SQL Set中
从AWR中提取:
DECLARE
SQLSET_CUR DBMS_SQLTUNE.SQLSET_CURSOR;
BEGIN
OPEN SQLSET_CUR FOR
SELECT VALUE(P) FROM TABLE(
DBMS_SQLTUNE.SELECT_WORKLOAD_REPOSITORY( 20, 21,
'PARSING_SCHEMA_NAME NOT IN (''SYS'', ''SYSTEM'')',
NULL, NULL, NULL, NULL, 1, NULL, 'ALL')) P;
DBMS_SQLTUNE.LOAD_SQLSET(
SQLSET_NAME => 'SOL_SQLSET_201906',
SQLSET_OWNER => 'SPA',
POPULATE_CURSOR => SQLSET_CUR,
LOAD_OPTION => 'MERGE',
UPDATE_OPTION => 'ACCUMULATE');
CLOSE SQLSET_CUR;
END;
/
查询sql set信息:
col DESCRIPTION for a50
select owner,name,STATEMENT_COUNT,DESCRIPTION,CREATED from dba_sqlset;
OWNER NAME STATEMENT_COUNT DESCRIPTION CREATED
------------------------------ ------------------------------ --------------- -------------------------------------------------- ---------
SPA SOL_SQLSET_201906 5 SQL Set Create at : 2019-06-17 23:57:05 17-JUN-19
d、转化当前cursor cache中的SQL数据,将其中的SQL载入到SQL Set中
从当前cursor cache中提取:排除sys、system用户执行的语句
DECLARE
SQLSET_CUR DBMS_SQLTUNE.SQLSET_CURSOR;
BEGIN
OPEN SQLSET_CUR FOR
SELECT VALUE(P) FROM TABLE(
DBMS_SQLTUNE.SELECT_CURSOR_CACHE(
'PARSING_SCHEMA_NAME NOT IN (''SYS'', ''SYSTEM'')',
NULL, NULL, NULL, NULL, 1, NULL,'ALL')) P;
DBMS_SQLTUNE.LOAD_SQLSET(
SQLSET_NAME => 'SOL_SQLSET_201906',
SQLSET_OWNER => 'SPA',
POPULATE_CURSOR => SQLSET_CUR,
LOAD_OPTION => 'MERGE',
UPDATE_OPTION => 'ACCUMULATE');
CLOSE SQLSET_CUR;
END;
/
查询sql set信息:
col DESCRIPTION for a50
select owner,name,STATEMENT_COUNT,DESCRIPTION,CREATED from dba_sqlset;
OWNER NAME STATEMENT_COUNT DESCRIPTION CREATED
------------------------------ ------------------------------ --------------- -------------------------------------------------- ---------
SPA SOL_SQLSET_201906 36 SQL Set Create at : 2019-06-17 23:57:05 17-JUN-19
e、打包SQL Set
DROP TABLE SPA.SOL_STSTAB_201906;
EXEC DBMS_SQLTUNE.CREATE_STGTAB_SQLSET ('SOL_STSTAB_201906', 'SPA', 'USERS');
EXEC DBMS_SQLTUNE.PACK_STGTAB_SQLSET ( -
SQLSET_NAME => 'SOL_SQLSET_201906', -
SQLSET_OWNER => 'SPA', -
STAGING_TABLE_NAME => 'SOL_STSTAB_201906', -
STAGING_SCHEMA_OWNER => 'SPA');
查看spa下用户下的表对象:
SQL> select * from tab;
TNAME TABTYPE CLUSTERID
------------------------------ ------- ----------
SOL_STSTAB_201906 TABLE
4.3.3、源端操作(导出SPA的数据)
打包(pack)转化后的SQL Tuning Set,并导出传输到测试服务器
将采集到的数据打包后,需要将其中生产库导出,并传输到测试服务器中,用于在测试数据库中进行SPA测试工作。
1)在操作系统中,导出打包后的SQL Set数据
[oracle@source ~]$ cat /home/oracle/export_sqlset_201903.par
USERID=spa/spa
FILE=SOL_STSTAB_201906.dmp
LOG=exp_spa_sqlset_201906.log
TABLES=SOL_STSTAB_201906
DIRECT=Y
BUFFER=10240000
STATISTICS=NONE
导出数据
[oracle@source ~]$ export NLS_LANG=AMERICAN_AMERICA.ZHS16GBK
[oracle@source ~]$ exp PARFILE=export_sqlset_201906.par
2)将导出后的Dump文件传输到测试服务器
将SOL_STSTAB_201906.dmp 传输到 目标服务器
4.3.4、目标端操作
1、环境准备
创建SPA专用用户
为了进行SPA测试,在测试数据库中创建SPA测试专用用户,避免与其他用户相互混淆与可能产生的误操作。
create user spa identified by spa default tablespace users;
grant dba to spa;
grant advisor to spa;
grant select any dictionary to spa;
grant administer sql tuning set to spa;
4.3.4、目标端操作
1、环境准备
创建SPA专用用户
为了进行SPA测试,在测试数据库中创建SPA测试专用用户,避免与其他用户相互混淆与可能产生的误操作。
create user spa identified by spa default tablespace users;
grant dba to spa;
grant advisor to spa;
grant select any dictionary to spa;
grant administer sql tuning set to spa;
2、测试准备
导入SQL Tuning Set表,并解包(unpack),创建SPA分析任务
在进行SPA测试前需要准备测试环境,包括导入生产库中的SQL Set,对其进行解包(unpack)操作,并创建SPA分析任务。
1)在操作系统中,执行导入命令,导入SQL Set表
C:\Users\li>imp USERID=spa/spa FILE=SOL_STSTAB_201906.dmp LOG=imp_spa_sqlset_201906.log FULL=Y
2)连接到spa
C:\Users\li>sqlplus spa/spa
3)解包(unpack)SQL Set
EXEC DBMS_SQLTUNE.UNPACK_STGTAB_SQLSET (-
SQLSET_NAME => 'SOL_SQLSET_201906', -
SQLSET_OWNER => 'SPA', -
REPLACE => TRUE, -
STAGING_TABLE_NAME => 'SOL_STSTAB_201906', -
STAGING_SCHEMA_OWNER => 'SPA');
4)创建SPA分析任务
VARIABLE SPA_TASK VARCHAR2(64);
EXEC :SPA_TASK := DBMS_SQLPA.CREATE_ANALYSIS_TASK( -
TASK_NAME => 'SPA_TASK_201906', -
DESCRIPTION => 'SPA Analysis task at : '||TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'), -
SQLSET_NAME => 'SOL_SQLSET_201906', -
SQLSET_OWNER => 'SPA');
建议设置设置超过时间,超过1800秒还未执行完成就跳过处理:
exec dbms_sqlpa.set_analysis_default_parameter('LOCAL_TIME_LIMIT',1800);
select parameter_value from dba_advisor_def_parameters where advisor_name='SQL Performance Analyzer' and parameter_name='LOCAL_TIME_LIMIT';
PARAMETER_VALUE
--------------------------------------------------------------------------------
1800
查看分析任务信息:
set linesize 400 pagesize 9999
col owner for a20
col task_name for a20
alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
select owner,task_id,task_name,created,last_modified,status from dba_advisor_tasks where task_name='SPA_TASK_201906' order by 2;
OWNER TASK_ID TASK_NAME CREATED LAST_MODIFIED STATUS
-------------------- ---------- -------------------- ------------------- ------------------- -----------
SPA 62 SPA_TASK_201906 2019-06-18 15:38:41 2019-06-18 15:38:42 INITIAL
3、前期性能
从SQL Tuning Set中转化得出11g的性能Trail
在测试服务器中,可以直接从SQL Tuning Set中转化得到所有SQL在11g数据库中的执行效率,得到11g中的SQL Trail。
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK( -
TASK_NAME => 'SPA_TASK_201906', -
EXECUTION_NAME => 'EXEC_11G_201906', -
EXECUTION_TYPE => 'CONVERT SQLSET', -
EXECUTION_DESC => 'Convert 11g SQLSET for SPA Task at : '||TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
4、后期性能
在19c测试数据库中执行SQL Tuning Set中SQL,生成19c性能Trail
在测试服务器(运行19据库)中,需要在本地数据库(19c)测试运行SQL Tuning Set中的SQL语句,分析所有语句在19c环境中的执行效率,得到19c中的SQL Trail。
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK( -
TASK_NAME => 'SPA_TASK_201906', -
EXECUTION_NAME => 'EXEC_19C_201906', -
EXECUTION_TYPE => 'TEST EXECUTE', -
EXECUTION_DESC => 'Execute SQL in 19c for SPA Task at : '||TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
5、对比报告
执行对比分析任务,分别按执行时间,CPU时间和逻辑读三个维度进行
得到两次SQL Trail之后,可以对比两次Trial之间的SQL执行性能,可以从不同的维度对两次Trail中的所有SQL进行对比分析,主要关注的维度有:SQL执行时间,SQL执行的CPU时间,SQL执行的逻辑读。
注意:在spa用户下执行
1)对比两次Trail中的SQL执行时间
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK( -
TASK_NAME => 'SPA_TASK_201906', -
EXECUTION_NAME => 'COMPARE_ET_201906', -
EXECUTION_TYPE => 'COMPARE PERFORMANCE', -
EXECUTION_PARAMS => DBMS_ADVISOR.ARGLIST( -
'COMPARISON_METRIC', 'ELAPSED_TIME', -
'EXECUTE_FULLDML', 'TRUE', -
'EXECUTION_NAME1','EXEC_11G_201906', -
'EXECUTION_NAME2','EXEC_19C_201906'), -
EXECUTION_DESC => 'Compare SQLs between 11g and 19c at :'||TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
2)对比两次Trail中的SQL执行的CPU时间
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK( -
TASK_NAME => 'SPA_TASK_201906', -
EXECUTION_NAME => 'COMPARE_CT_201906', -
EXECUTION_TYPE => 'COMPARE PERFORMANCE', -
EXECUTION_PARAMS => DBMS_ADVISOR.ARGLIST( -
'COMPARISON_METRIC', 'CPU_TIME', -
'EXECUTION_NAME1','EXEC_11G_201906', -
'EXECUTION_NAME2','EXEC_19C_201906'), -
EXECUTION_DESC => 'Compare SQLs between 11g and 19c at :'||TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
3)对比两次Trail中的SQL执行的逻辑读
EXEC DBMS_SQLPA.EXECUTE_ANALYSIS_TASK( -
TASK_NAME => 'SPA_TASK_201906', -
EXECUTION_NAME => 'COMPARE_BG_201906', -
EXECUTION_TYPE => 'COMPARE PERFORMANCE', -
EXECUTION_PARAMS => DBMS_ADVISOR.ARGLIST( -
'COMPARISON_METRIC', 'BUFFER_GETS', -
'EXECUTION_NAME1','EXEC_11G_201906', -
'EXECUTION_NAME2','EXEC_19C_201906'), -
EXECUTION_DESC => 'Compare SQLs between 11g and 19c at :'||TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS'));
6、汇总报告
取出对比报告,对每个维度分别取出All,Unsupport,Error 3类报告
执行对比分析任务之后,就可以取出对应的对比分析任务的结果报告,主要关注的报告类型有:汇总SQL报告,错误SQL报告以及不支持SQL报告。
1)获取执行时间全部报告
ALTER SESSION SET EVENTS='31156 TRACE NAME CONTEXT FOREVER, LEVEL 0X400';
SET LINES 1111 PAGES 50000 LONG 1999999999 TRIM ON TRIMS ON SERVEROUTPUT ON SIZE UNLIMITED
SPOOL elapsed_all.html
SELECT XMLTYPE(DBMS_SQLPA.REPORT_ANALYSIS_TASK('SPA_TASK_201906','HTML','ALL','ALL',NULL,3000,'COMPARE_ET_201906')).GETCLOBVAL(0,0) FROM DUAL;
spool off
2)获取执行时间下降报告
ALTER SESSION SET EVENTS='31156 TRACE NAME CONTEXT FOREVER, LEVEL 0X400';
SET LINES 1111 PAGES 50000 LONG 1999999999 TRIM ON TRIMS ON SERVEROUTPUT ON SIZE UNLIMITED
SPOOL elapsed_regressed.html
SELECT XMLTYPE(DBMS_SQLPA.REPORT_ANALYSIS_TASK('SPA_TASK_201903','HTML','REGRESSED','ALL',NULL,NULL,'COMPARE_ET_201903')).GETCLOBVAL(0,0) FROM DUAL;
spool off
3)获取逻辑读全部报告
ALTER SESSION SET EVENTS='31156 TRACE NAME CONTEXT FOREVER, LEVEL 0X400';
SET LINES 1111 PAGES 50000 LONG 1999999999 TRIM ON TRIMS ON SERVEROUTPUT ON SIZE UNLIMITED
SPOOL buffer_all.html
SELECT XMLTYPE(DBMS_SQLPA.REPORT_ANALYSIS_TASK('SPA_TASK_201906','HTML','ALL','ALL',NULL,3000,'COMPARE_BG_201906')).GETCLOBVAL(0,0) FROM DUAL;
spool off
4)获取逻辑读下降报告
ALTER SESSION SET EVENTS='31156 TRACE NAME CONTEXT FOREVER, LEVEL 0X400';
SET LINES 1111 PAGES 50000 LONG 1999999999 TRIM ON TRIMS ON SERVEROUTPUT ON SIZE UNLIMITED
SPOOL buffer_regressed.html
SELECT XMLTYPE(DBMS_SQLPA.REPORT_ANALYSIS_TASK('SPA_TASK_201906','HTML','REGRESSED','ALL',NULL,NULL,'COMPARE_BG_201906')).GETCLOBVAL(0,0) FROM DUAL;
spool off
5)获取错误报告
ALTER SESSION SET EVENTS='31156 TRACE NAME CONTEXT FOREVER, LEVEL 0X400';
SET LINES 1111 PAGES 50000 LONG 1999999999 TRIM ON TRIMS ON SERVEROUTPUT ON SIZE UNLIMITED
SPOOL error.html
SELECT XMLTYPE(DBMS_SQLPA.REPORT_ANALYSIS_TASK('SPA_TASK_201906','HTML','ERRORS','ALL',NULL,NULL,'COMPARE_ET_201906')).GETCLOBVAL(0,0) FROM DUAL;
spool off
6)获取不支持报告
ALTER SESSION SET EVENTS='31156 TRACE NAME CONTEXT FOREVER, LEVEL 0X400';
SET LINES 1111 PAGES 50000 LONG 1999999999 TRIM ON TRIMS ON SERVEROUTPUT ON SIZE UNLIMITED
SPOOL unsupported.html
SELECT XMLTYPE(DBMS_SQLPA.REPORT_ANALYSIS_TASK('SPA_TASK_201906','HTML','UNSUPPORTED','ALL',NULL,NULL,'COMPARE_ET_201906')).GETCLOBVAL(0,0) FROM DUAL;
spool off
7)获取执行计划变化报告
ALTER SESSION SET EVENTS='31156 TRACE NAME CONTEXT FOREVER, LEVEL 0X400';
SET LINES 1111 PAGES 50000 LONG 1999999999 TRIM ON TRIMS ON SERVEROUTPUT ON SIZE UNLIMITED
SPOOL changed_plans.html
SELECT XMLTYPE(DBMS_SQLPA.REPORT_ANALYSIS_TASK('SPA_TASK_201906','HTML','CHANGED_PLANS','ALL',NULL,3000,'COMPARE_ET_201906')).GETCLOBVAL(0,0) FROM DUAL;
spool off
8)获取执行超时报告
ALTER SESSION SET EVENTS='31156 TRACE NAME CONTEXT FOREVER, LEVEL 0X400';
SET LINES 1111 PAGES 50000 LONG 1999999999 TRIM ON TRIMS ON SERVEROUTPUT ON SIZE UNLIMITED
SPOOL timeout.html
SELECT XMLTYPE(DBMS_SQLPA.REPORT_ANALYSIS_TASK('SPA_TASK_201906','HTML','TIMEOUT','ALL',NULL,NULL,'COMPARE_ET_201906')).GETCLOBVAL(0,0) FROM DUAL;
spool off
最终的SPA性能分析报告