Oracle - SPM固定执行计划(二)
一、前言
前面文章(https://www.cnblogs.com/ddzj01/p/11365541.html)给大家介绍了当一条sql有多个执行计划时,如何通过spm去绑定其中一条执行计划。本文将继续介绍,如何给一条sql注入一个新的执行计划,去替换原始的执行计划。
二、解决办法
1. 生成初始执行计划所对应的sql plan baseline
begin
:temp := dbms_spm.load_plans_from_cursor_cache(
sql_id => '原目标sql的sql_id',
plan_hash_value => 原目标sql的plan hash value);
end;
/
2. 查出该sql的sql_handle
select sql_handle, sql_text, plan_name, origin from dba_sql_plan_baselines where sql_text like '原目标sql的sql_text%';
3. 生成新的sql plan baseline
begin
:temp := dbms_spm.load_plans_from_cursor_cache(
sql_id => '加入合适hint后改写的sql的sql_id',
plan_hash_value => 加入合适hint后改写的sql的plan hash value,
sql_handle => '原目标sql在步骤(1)中所产生的sql_handle');
end;
/
4. 删除步骤(1)中所产生的sql plan baseline
begin
:temp := dbms_spm.drop_sql_plan_baseline(
sql_handle => '原目标sql在步骤(1)中的sql_handle',
plan_name => '原目标sql在步骤(1)中的plan_name');
end;
/
就这么写,肯定一脸懵逼,下面通过一个实验去解释。
三、做个实验
实验环境,使用scott账号,并给scott赋予dba权限(实际上scott只需要administer sql management object权限就可以使用spm)
创建表和索引,并收集统计信息
SQL> create table test2 as select * from dba_objects;
SQL> create index idx_test2 on test2(object_id) online;
SQL> begin
dbms_stats.gather_table_stats(ownname=>'SCOTT',
tabname=>'TEST2',
cascade=>true,
no_invalidate=>false);
end;
/
执行原始的sql
SQL> set autot trace
SQL> select * from test2 where object_id=20;
Execution Plan
----------------------------------------------------------
Plan hash value: 4047680367 -----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 98 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TEST2 | 1 | 98 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | IDX_TEST2 | 1 | | 1 (0)| 00:00:01 |
-----------------------------------------------------------------------------------------
可以看到原始sql的执行计划为索引范围扫描
新开一个窗口,查原始sql的sql_id和plan_hash_value
SQL> col sql_id for a20
SQL> col sql_text for a40
SQL> select sql_id, plan_hash_value, sql_text from v$sqlarea where sql_text like 'select * from test2 where object_id=20%';
SQL_ID PLAN_HASH_VALUE SQL_TEXT
-------------------- --------------- ----------------------------------------
4tm6j886yvzj3 4047680367 select * from test2 where object_id=20
将原始sql语句加入基线
SQL> var temp number;
SQL> begin
:temp := dbms_spm.load_plans_from_cursor_cache(sql_id=>'4tm6j886yvzj3', plan_hash_value=>4047680367);
end;
/
查看原始sql的基线
SQL> col sql_handle for a24
SQL> col sql_text for a40
SQL> col plan_name for a35
SQL> select sql_handle, sql_text, plan_name, origin from dba_sql_plan_baselines where sql_text like 'select * from test2 where object_id=20%';
SQL_HANDLE SQL_TEXT PLAN_NAME ORIGIN
------------------------ ---------------------------------------- ----------------------------------- --------------
SQL_20df29fdb3e8ac52 select * from test2 where object_id=20 SQL_PLAN_21rt9zqtyjb2k60b1ef84 MANUAL-LOAD
对原始sql加hint,执行新的sql
SQL> select /*+ full(test2) */ * from test2 where object_id=20;
获得新sql语句的sql_id和plan_hash_value
SQL> select sql_id, plan_hash_value, sql_text from v$sqlarea where sql_text like 'select /*+ full(test2) */%';
SQL_ID PLAN_HASH_VALUE SQL_TEXT
-------------------- --------------- ----------------------------------------
11cptg7m2vcwr 300966803 select /*+ full(test2) */ * from test2 w
here object_id=20
将新的sql_id和plan_hash_value加入到原始sql的基线中
SQL> var temp number;
SQL> begin
:temp := dbms_spm.load_plans_from_cursor_cache(sql_id=>'11cptg7m2vcwr', plan_hash_value=>300966803, sql_handle =>'SQL_20df29fdb3e8ac52');
end;
/
查看原始sql的基线
SQL> select sql_handle, sql_text, plan_name, origin from dba_sql_plan_baselines where sql_text like 'select * from test2 where object_id=20%';
SQL_HANDLE SQL_TEXT PLAN_NAME ORIGIN
------------------------ ---------------------------------------- ----------------------------------- --------------
SQL_20df29fdb3e8ac52 select * from test2 where object_id=20 SQL_PLAN_21rt9zqtyjb2k60b1ef84 MANUAL-LOAD
SQL_20df29fdb3e8ac52 select * from test2 where object_id=20 SQL_PLAN_21rt9zqtyjb2k99963deb MANUAL-LOAD
可以看到新的执行计划plan_name为SQL_PLAN_21rt9zqtyjb2k99963deb已经加到原始sql的基线中了
删除旧的sql_plan
SQL> var temp number;
SQL> begin
:temp := dbms_spm.drop_sql_plan_baseline(sql_handle =>'SQL_20df29fdb3e8ac52', plan_name=>'SQL_PLAN_21rt9zqtyjb2k60b1ef84');
end;
/
新开一个窗口,再运行原始sql语句
SQL> set autot trace
SQL> select * from test2 where object_id=20;
Execution Plan
----------------------------------------------------------
Plan hash value: 300966803 ---------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 98 | 347 (1)| 00:00:05 |
|* 1 | TABLE ACCESS FULL| TEST2 | 1 | 98 | 347 (1)| 00:00:05 |
--------------------------------------------------------------------------- Note
-----
- SQL plan baseline "SQL_PLAN_21rt9zqtyjb2k99963deb" used for this statement
可以看到原始sql的执行计划已经改变了。
四、总结
spm只是一个临时应急解决方案,数据库出现执行计划不正确,应该从源头查找原因,比如说统计信息,索引是否失效等等。
Oracle - SPM固定执行计划(二)的更多相关文章
- Oracle - SPM固定执行计划
1. 通过dbms_xplan.display_cursor查看指定sql都有哪些执行计划 SQL> select * from table(dbms_xplan.display_cursor( ...
- Oracle - SPM固定执行计划(一)
一.前言 生产中偶尔会碰到一些sql,有多种执行计划,其中部分情况是统计信息过旧造成的,重新收集下统计信息就行了.但是有些时候重新收集统计信息也解决不了问题,而开发又在嗷嗷叫,没时间让你去慢慢分析原因 ...
- SQL Server如何固定执行计划
SQL Server 其实从SQL Server 2005开始,也提供了类似ORACLE中固定执行计划的功能,只是好像很少人使用这个功能.当然在SQL Server中不叫"固定执行计划&qu ...
- Oracle 固定执行计划-使用SPM(Sql Plan Management)固定执行计划
固定执行计划-使用SPM(Sql Plan Management)固定执行计划 转载自:http://www.lunar2013.com/2016/01/固定执行计划-使用spm%EF%BC%88sq ...
- 基于Oracle的SQL优化(崔华著)-整理笔记-第2章“Oracle里的执行计划”
详细介绍了Oracle数据里与执行计划有关的各个方面的内容,包括执行计划的含义,加何查看执行计划,如何得到目标SQL真实的执行计划,如何查看执行计划的执行顺序,Oracle数据库里各种常见的执行计划的 ...
- 固定执行计划-SQL PROFILE手工绑定
固定(稳定)执行计划 你的应用的功能时快时慢,变化比较大,功能的性能能够保持一种稳定的状态,ORACLE 固定执行计划,采用以下这几种方式 oracle 9i使用 Outline oracle 10g ...
- Oracle性能优化之Oracle里的执行计划
一.执行计划 执行计划是目标SQL在oracle数据库中具体的执行步骤,oracle用来执行目标SQL语句的具体执行步骤的组合被称为执行计划. 二.如何查看oracle数据库的执行计划 oracle数 ...
- Oracle中获取执行计划的几种方法分析
以下是对Oracle中获取执行计划的几种方法进行了详细的分析介绍,需要的朋友可以参考下 1. 预估执行计划 - Explain PlanExplain plan以SQL语句作为输入,得到这条S ...
- Oracle查看SQL执行计划的方式
Oracle查看SQL执行计划的方式 获取Oracle sql执行计划并查看执行计划,是掌握和判断数据库性能的基本技巧.下面案例介绍了多种查看sql执行计划的方式: 基本有以下几种方式: ...
随机推荐
- 01-EF Core笔记之创建模型
使用EF Core的第一步是创建数据模型,模型建的好,下班走的早.EF Core本身已经设置了一系列约定来帮我们快速的创建模型,例如表名.主键字段等,毕竟约定大于配置嘛.如果你想改变默认值,很简单,E ...
- django admin配置以及使用
admin组件使用 Django 提供了基于 web 的管理工具(django 2.0+, python3.6+). Django 自动管理工具是 django.contrib 的一部分.你可以在项目 ...
- WPF引用WinForm控件
前言:在WPF开发当中由于DataGrid控件实现业务未达到非常理想的效果,我决定使用WinForm中的DataGridView来实现业务. 在XAML中加入以下命名空间: xmlns:wf=&quo ...
- MongoDB安装与Spring整合
MongoDB是面向文档的非关系型数据库,数据模型是一种类似于JSON的结构,在数据库中存的是各种各样的JSON.官网下载地址:https://www.mongodb.com/download-cen ...
- DG中switchover切换操作
问题描述:我们配置DG的目的就是为了在主库出现故障时,备库能够提供服务,保证业务的正常运行,switchover是用户有计划的进行停机切换,能够保证不丢失数据,我记录一下我进行switchover中的 ...
- asp.net core 3.0 选项模式1:使用
本篇只是从应用角度来说明asp.net core的选项模式,下一篇会从源码来分析 1.以前的方式 以前我们使用web.config/app.config时是这样使用配置的 var count = Co ...
- 前端小白webpack学习(四)
.less文件与.scss文件使用与.css文件相仿 less-loader使用需要借助less插件,终端输入npm i less less-loader -D安装; sass-loader使用需要借 ...
- Docker系列之原理简单介绍
目录 1.1.Docker架构简介 1.2.Docker 两个主要部件 1.3.虚拟机和Docker对比: 1.4.Docker内部结构 Docker系列之原理简单介绍 @ Docker是一个开源的应 ...
- ETCD:客户端v3
原文地址:etcd/clientv3 etcd/clientv3是v3版本的Go etcd官方客户端 安装 go get go.etcd.io/etcd/clientv3 开始 创建客户端使用clie ...
- .Net Core组件化视图(部分视图)
.Net Core组件化视图(部分视图) 1.背景 1.以前我们使用.Net的时候使用部分视图的方式在,.Net Core 中能在单独处理逻辑的部分视图没有了,但是我们还是想使用现在的.Net Cor ...