关于号主,姚远:
Oracle ACE(Oracle和MySQL数据库方向)
华为云最有价值专家
《MySQL 8.0运维与优化》的作者
拥有 Oracle 10g、12c和19c OCM等数十项数据库认证
曾任IBM公司数据库部门经理
20+年DBA经验,服务2万+客户
精通C和Java,发明两项计算机专利
使用SQL执行计划基线可以保证SQL的性能不下降,但实际生产中默认没有开启,这里是姚远老师在给OCM的学员授课中关于SQL执行计划基线的一个案例,大家可以借鉴一下。
01
—
修改配置,采集SQL执行计划基线
Oracle 19c与SQL执行计划基线相关的默认参数值如下:
SQL> show parameter baselineNAME TYPE VALUE------------------------------------ ----------- ------------------------------optimizer_capture_sql_plan_baselines boolean FALSEoptimizer_use_sql_plan_baselines boolean TRUE
使用存储过程DBMS_SPM.CONFIGURE修改配置,自动捕捉TPCC用户执行的SQL,并创建基线:
EXEC DBMS_SPM.CONFIGURE('AUTO_CAPTURE_PARSING_SCHEMA_NAME','TPCC',true);alter system set optimizer_capture_sql_plan_baselines=true;
修改后的参数存放在视图DBA_SQL_MANAGEMENT_CONFIG中,检查一下:
COL PARAMETER_NAME FORMAT a32COL PARAMETER_VALUE FORMAT a32SELECT PARAMETER_NAME, PARAMETER_VALUE FROM DBA_SQL_MANAGEMENT_CONFIG ;PARAMETER_NAME PARAMETER_VALUE-------------------------------- --------------------------------AUTO_CAPTURE_ACTIONAUTO_CAPTURE_MODULEAUTO_CAPTURE_PARSING_SCHEMA_NAME parsing_schema IN (TPCC)AUTO_CAPTURE_SQL_TEXTAUTO_SPM_EVOLVE_TASK OFFAUTO_SPM_EVOLVE_TASK_INTERVAL 3600 --AUTO_SPM_EVOLVE_TASK_MAX_RUNTIME 1800PLAN_RETENTION_WEEKS 53 -- 53不用的计划会被清理SPACE_BUDGET_PERCENT 10 -- 占用SYSAUX的空间不超过10%,超过在alert中报警9 rows selected.
02
—
查看SQL执行计划基线的应用
先将一个索引改成不可见:
SQL> alter index tpcc.CUSTOMER_I1 invisible;Index altered.
应用运行一段时间后,检查已经创建的SQL基线:
SQL> select count(distinct sql_handle),count(distinct plan_name),count(distinct SIGNATURE) from DBA_SQL_PLAN_BASELINES;COUNT(DISTINCTSQL_HANDLE) COUNT(DISTINCTPLAN_NAME) COUNT(DISTINCTSIGNATURE)------------------------- ------------------------ ------------------------30 30 30
可以看到为30个SQL建立了基线,都是ACCEPTED,因为每个SQL只有一个执行计划。
检查与这个索引相关的SQL的执行情况:
SQL> select SQL_ID,EXECUTIONS,OPTIMIZER_COST,SQL_PLAN_BASELINE from v$sql where sql_id='arykx3hpq9xsa';SQL_ID EXECUTIONS OPTIMIZER_COST SQL_PLAN_BASELINE------------- ---------- -------------- ------------------------------arykx3hpq9xsa 5102 1945 SQL_PLAN_2v1cfx8jds3vt3a6ea7ea
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_SQL_PLAN_BASELINE('SQL_2d858eea22dc0f79','SQL_PLAN_2v1cfx8jds3vt3a6ea7ea','basic') );PLAN_TABLE_OUTPUT--------------------------------------------------------------------------------SQL handle: SQL_2d858eea22dc0f79SQL text: UPDATE CUSTOMER SET C_BALANCE = C_BALANCE + :B1 WHERE C_W_ID = :B4AND C_D_ID = :B3 AND C_ID = :B2----------------------------------------------------------------------------------------------------------------------------------------------------------------Plan name: SQL_PLAN_2v1cfx8jds3vt3a6ea7ea Plan id: 980330474Enabled: YES Fixed: NO Accepted: YES Origin: AUTO-CAPTUREPlan rows: From dictionary--------------------------------------------------------------------------------Plan hash value: 3529770744----------------------------------------| Id | Operation | Name |----------------------------------------| 0 | UPDATE STATEMENT | || 1 | UPDATE | CUSTOMER || 2 | INDEX SKIP SCAN| CUSTOMER_I2 |----------------------------------------22 rows selected.
set pagesize 200SELECT PLAN_TABLE_OUTPUT FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR('arykx3hpq9xsa'));
将这个索引改成可见:
alter index tpcc.CUSTOMER_I1 visible;
第二次执行应用程序,然后再检查这个SQL的执行情况:
SQL> select SQL_ID,EXECUTIONS,OPTIMIZER_COST,SQL_PLAN_BASELINE from v$sql where sql_id='arykx3hpq9xsa';SQL_ID EXECUTIONS OPTIMIZER_COST SQL_PLAN_BASELINE------------- ---------- -------------- ------------------------------arykx3hpq9xsa 2376 1945 SQL_PLAN_2v1cfx8jds3vt3a6ea7ea
col plan_name form a30col signature forma 99999999999999999999999select sql_handle,plan_name,signature,accepted,optimizer_cost from DBA_SQL_PLAN_BASELINESwhere SIGNATURE=(select EXACT_MATCHING_SIGNATURE from v$sql where sql_id='arykx3hpq9xsa');SQL_HANDLE PLAN_NAME SIGNATURE ACC OPTIMIZER_COST------------------------------ ------------------------------ ------------------------ --- --------------SQL_2d858eea22dc0f79 SQL_PLAN_2v1cfx8jds3vt341d91fc 3280185039867613049 NO 3SQL_2d858eea22dc0f79 SQL_PLAN_2v1cfx8jds3vt3a6ea7ea 3280185039867613049 YES 1945

03
—
手工进化基线
因为SQL基线的进化任务要到晚上维护窗口时才会执行,新的基线没有进化成可接受的,所以SQL执行时不会选择这个基线,我们可以手工对这个SQL基线进行进化:
VARIABLE cnt NUMBERVARIABLE tk_name VARCHAR2(50)VARIABLE exe_name VARCHAR2(50)VARIABLE evol_out CLOBbegin:tk_name := DBMS_SPM.CREATE_EVOLVE_TASK(sql_handle => 'SQL_2d858eea22dc0f79',plan_name => 'SQL_PLAN_2v1cfx8jds3vt341d91fc');end;/SELECT :tk_name FROM DUAL;SQL> SELECT :tk_name FROM DUAL;:TK_NAME-----------------------TASK_1551EXECUTE :exe_name :=DBMS_SPM.EXECUTE_EVOLVE_TASK(task_name=>:tk_name);SELECT :exe_name FROM DUAL;:EXE_NAME--------------------------------EXEC_3452
检查这个进化计划的执行报告:
EXECUTE :evol_out := DBMS_SPM.REPORT_EVOLVE_TASK( task_name=>:tk_name, execution_name=>:exe_name );SELECT :evol_out FROM DUAL;SQL> SELECT :evol_out FROM DUAL;:EVOL_OUT--------------------------------------------------------------------------------GENERAL INFORMATION SECTION----------------------------------------------------Task Information:---------------------------------------------Task Name : TASK_1551Task Owner : SYSExecution Name : EXEC_3452Execution Type : SPM EVOLVEScope : COMPREHENSIVEStatus : COMPLETEDStarted : 09/08/2023 15:21:50Finished : 09/08/2023 15:21:50Last Updated : 09/08/2023 15:21:50Global Time Limit : 2147483646Per-Plan Time Limit : UNUSEDNumber of Errors : 0-----------------------------------------SUMMARY SECTION--------------------------------------------------7 Number of plans processed : 1Number of findings : 1Number of recommendations : 1Number of errors : 0---------------------------------------------------------------------------------------------DETAILS SECTION---------------------------------------------------------------------------------------------Object ID : 2Test Plan Name : SQL_PLAN_2v1cfx8jds3vt341d91fcBase Plan Name : SQL_PLAN_2v1cfx8jds3vt3a6ea7eaSQL Handle : SQL_2d858eea22dc0f79Parsing Schema : TPCCTest Plan Creator : SYSSQL Text : UPDATE CUSTOMER SET C_BALANCE = C_BALANCE + :B1 WHEREC_W_ID = :B4 AND C_D_ID= :B3 AND C_ID = :B2Bind Variables:-----------------------------2 - (NUMBER): 33 - (NUMBER): 14 - (NUMBER): 2285Execution Statistics:-----------------------------Base PlanTest Plan---------------------------- ----------------------------Elapsed Time (s): .00064 .000002CPU Time (s): .000638 .000002Buffer Gets: 117 0Optimizer Cost: 1945 3Disk Reads: 0 0Direct Writes: 0 0Rows Processed: 0 0Executions: 10 10FINDINGS SECTION-----------------------------------------Findings (1):-----------------------------1. The plan was verified in 0.12000 seconds. It passed the benefit criterionbecause its verified performance was 390.90001 times better than that ofthe baseline plan.Recommendation:-----------------------------Consider accepting the plan. Executedbms_spm.accept_sql_plan_baseline(task_name => 'TASK_1551', object_id => 2,task_owner => 'SYS');EXPLAIN PLANS SECTION---------------------------------------------Baseline Plan-----------------------------Plan Id : 9217Plan Hash Value : 980330474-------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | Time |---------------------------------------------------------------------------| 0 | UPDATE STATEMENT | | 1 | 15 | 1945 | 00:00:01 || 1 | UPDATE | CUSTOMER | | | | || * 2 | INDEX SKIP SCAN | CUSTOMER_I2 | 1 | 15 | 1944 | 00:00:01 |-----------------------------------------------Predicate Information (identified by operation id):------------------------------------------* 2 - access("C_W_ID"=:B4 AND "C_D_ID"=:B3 AND "C_ID"=:B2)* 2 - filter("C_ID"=:B2 AND "C_W_ID"=:B4 AND "C_D_ID"=:B3)Test Plan-----------------------------Plan Id : 9218Plan Hash Value : 874353148----------------------------------------------------| Id | Operation | Name | Rows | Bytes | Cost | Time |--------------------------------------------------------| 0 | UPDATE STATEMENT | | 1 | 15| 3 | 00:00:01 || 1 | UPDATE | CUSTOMER | | | | || * 2 | INDEX UNIQUE SCAN | CUSTOMER_I1 | 1 | 15 | 2 | 00:00:01 |--------------------------------------------Predicate Information (identified by operation id):------------------------------------------* 2 - access("C_W_ID"=:B4 AND "C_D_ID"=:B3 AND "C_ID"=:B2)--------------------------------------------------
根据报告中的建议,执行下面的SQL接受第二个基线:
SQL> exec dbms_spm.accept_sql_plan_baseline(task_name => 'TASK_1551', object_id => 2, task_owner => 'SYS');PL/SQL procedure successfully completed.
再次检查这个SQL对应的执行计划基线:
col plan_name form a30col signature forma 99999999999999999999999select sql_handle,plan_name,signature,accepted,optimizer_cost from DBA_SQL_PLAN_BASELINES2 where SIGNATURE=(select EXACT_MATCHING_SIGNATURE from v$sql where sql_id='arykx3hpq9xsa');SQL_HANDLE PLAN_NAME SIGNATURE ACC OPTIMIZER_COST------------------------------ ------------------------------ ------------------------ --- --------------SQL_2d858eea22dc0f79 SQL_PLAN_2v1cfx8jds3vt341d91fc 3280185039867613049 YES 3SQL_2d858eea22dc0f79 SQL_PLAN_2v1cfx8jds3vt3a6ea7ea 3280185039867613049 YES 1945
发现两个基线都是接受的。
第三次执行应用后,然后检查SQL的执行情况:
SQL> select SQL_ID,EXECUTIONS,OPTIMIZER_COST,SQL_PLAN_BASELINE from v$sql where sql_id='arykx3hpq9xsa';SQL_ID EXECUTIONS OPTIMIZER_COST SQL_PLAN_BASELINE------------- ---------- -------------- ------------------------------arykx3hpq9xsa 6849 3 SQL_PLAN_2v1cfx8jds3vt341d91fc
发现应用的SQL采用了第二个基线,执行成本从1945降低到3。
04
—
删除SQL基线
使用dbms_spm.drop_sql_plan_baseline可以删除SQL基线,但不能一次删除所有的SQL基线,如果要删除所有的SQL基线,需要用游标进行循环删除 ,相关程序如下(参见Doc ID 790039.1)
declarepgn number;sqlhdl varchar2(30);cursor hdl_cur isselect distinct sql_handle from dba_sql_plan_baselines;beginopen hdl_cur;loopfetch hdl_cur into sqlhdl;exit when hdl_cur%NOTFOUND;pgn := dbms_spm.drop_sql_plan_baseline(sql_handle=>sqlhdl);end loop;close hdl_cur;commit;end;/PL/SQL procedure successfully completed.SQL> select count(*) from dba_sql_plan_baselines;COUNT(*)----------0
欢迎加我的微信,拉你进数据库微信群👇

推荐文章👇
托业890分的Oracle ACE为您翻译国际大佬的雄文(合集)




