Oracle 学习之性能优化(三)绑定变量

根据Oracle 学习之性能优化(二)游标中的描述,我们知道如下两条语句是不共享的。

select * from emp where empno=7698;
select * from emp where empno=7566;

这样就造成每次执行用户的查询都要进行硬解析,但是我们知道,其他这两个语句的执行计划应该是相同。那么有什么方法能避免不必要的硬解析吗?这里我们提供2种方法。

一、绑定变量

SQL> variable empno number;
SQL> exec :empno := 7839;

PL/SQL procedure successfully completed.

SQL> select ename from emp where empno = :empno;

ENAME
------------------------------
KING

SQL>  exec :empno := 7782;

PL/SQL procedure successfully completed.

SQL> select ename from emp where empno = :empno;

ENAME
------------------------------
CLARK

SQL>

我们查看一下游标

SQL> COL SQL_TEXT FOR A30
SQL> COL SQL_ID FOR A20
SQL> SET LINESIZE 200
SQL> SELECT sql_id,sql_text,executions,loads,version_count
  FROM v$sqlarea
 WHERE sql_text LIKE ‘%:empno‘; 

SQL_ID		     SQL_TEXT			    EXECUTIONS	    LOADS VERSION_COUNT
-------------------- ------------------------------ ---------- ---------- -------------
f6r0kqk0hsa7s	     select ename from emp where em	     2		1	      1
		     pno = :empno

SQL> SELECT sql_id,sql_text,loads,child_number,parse_calls
  FROM v$sql
 WHERE sql_text LIKE ‘%:empno‘;

SQL_ID		     SQL_TEXT				 LOADS CHILD_NUMBER PARSE_CALLS
-------------------- ------------------------------ ---------- ------------ -----------
f6r0kqk0hsa7s	     select ename from emp where em	     1		  0	      2
		     pno = :empno
SQL>

可见,父子游标都被共享啦。

在OLTP环境中,一定要使用绑定变量以避免系统有太多的硬解析。

我们验证一下,不使用绑定变量和使用了绑定变量后,性能到底有没有提升。

1. 建立一张表

SQL> create table t(id int,text varchar2(100));

Table created.

2. 不使用绑定变量向表中插入10000行记录

SQL> set timing on
SQL> declare
begin
  for i in 1 .. 10000 loop
     execute immediate ‘insert into t values(‘||i||‘,‘‘test bind variable‘‘)‘;
  end loop;
  commit;
end;
/ 

PL/SQL procedure successfully completed.

Elapsed: 00:00:06.43

系统产生了非常多的游标

SQL> set pause on
SQL> SELECT sql_text,
       sql_id,
       EXECUTIONS,
       LOADS,
       VERSION_COUNT
  FROM v$sqlarea
 WHERE sql_text LIKE ‘insert into t%‘;   

SQL_TEXT		       SQL_ID		    EXECUTIONS	    LOADS VERSION_COUNT
------------------------------ -------------------- ---------- ---------- -------------
insert into t values(9156,‘tes ah7vdgtnj80b1		     1		1	      1
t bind variable‘)

insert into t values(8826,‘tes 7yuz09vq9h0c4		     1		1	      1
t bind variable‘)

insert into t values(9905,‘tes 97c7m0gxj80cv		     1		1	      1
t bind variable‘)

insert into t values(9396,‘tes 9bvtw8y7080g5		     1		1	      1
t bind variable‘)

SQL_TEXT		       SQL_ID		    EXECUTIONS	    LOADS VERSION_COUNT
------------------------------ -------------------- ---------- ---------- -------------

insert into t values(9034,‘tes ck51y8bu1c0jr		     1		1	      1
t bind variable‘)

insert into t values(9153,‘tes 7cxb26zpcn0q9		     1		1	      1
t bind variable‘)

insert into t values(9783,‘tes 7236x7yva40sq		     1		1	      1
t bind variable‘)

insert into t values(9491,‘tes cn2n05f70810f		     1		1	      1

3. 使用绑定变量

SQL> set timing on
SQL> declare
begin
  for i in 1 .. 10000 loop
     execute immediate ‘insert into t values(:x,‘‘test bind variable‘‘)‘ using i;
  end loop;
  commit;
end;
/ 

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.43

使用绑定变量,执行速度快了很多倍。

SQL> SELECT sql_text,
       sql_id,
       EXECUTIONS,
       LOADS,
       VERSION_COUNT
  FROM v$sqlarea
 WHERE sql_text LIKE ‘insert into t%:x%‘; 

SQL_TEXT		       SQL_ID		    EXECUTIONS	    LOADS VERSION_COUNT
------------------------------ -------------------- ---------- ---------- -------------
insert into t values(:x,‘test  0nhbks92x50kk		 10000		1	      1
bind variable‘)

执行计划只有一个,被执行了10000次。

二、修改初始化参数

系统提供了一个初始化参数

SQL> show parameter cursor_sharing
NAME				     TYPE			       VALUE
------------------------            -------------------               ------------------
cursor_sharing			     string			       EXACT

CURSOR_SHARING determines what kind of SQL statements can share the same
cursors.

Values:

  • FORCE
    Allows the creation of a new cursor if sharing an existing cursor, or if the cursor
    plan is not optimal.
  • SIMILAR
    Causes statements that may differ in some literals, but are otherwise identical, to
    share a cursor, unless the literals affect either the meaning of the statement or the
    degree to which the plan is optimized.
  • EXACT
    Only allows statements with identical text to share the same cursor

1. 清空shared_pool

SQL> set pagesize 10000
SQL> set linesize 200
SQL> col SQL_TEXT for a50
SQL> col SQL_ID for 520
SQL> col SQL_ID for a20
SQL> alter system flush shared_pool;

System altered.

SQL> SELECT sql_text,
       sql_id,
       EXECUTIONS,
       LOADS,
       VERSION_COUNT
  FROM v$sqlarea
 WHERE sql_text LIKE ‘insert into t%‘;   2    3    4    5    6    7  

no rows selected

SQL>

2. 将cursor_sharing改为FORCE,执行查询

SQL>  alter session set cursor_sharing=force;

Session altered.

Elapsed: 00:00:00.02
SQL> declare
begin
  for i in 1 .. 10000 loop
     execute immediate ‘insert into t values(‘||i||‘,‘‘test bind variable‘‘)‘;
  end loop;
  commit;
end;
/  2    3    4    5    6    7    8  

PL/SQL procedure successfully completed.

Elapsed: 00:00:01.15

3. 查看游标情况

SQL> SELECT sql_text,
       sql_id,
       EXECUTIONS,
       LOADS,
       VERSION_COUNT
  FROM v$sqlarea
 WHERE sql_text LIKE ‘insert into t%‘;

no rows selected

SQL> /

SQL_TEXT					   SQL_ID		EXECUTIONS	LOADS VERSION_COUNT
-------------------------------------------------- -------------------- ---------- ---------- -------------
insert into t values(9966,‘test bind variable‘)    07xgdm0uwn5gb		 1	    3		  1
insert into t values(10000,‘test bind variable‘)   76rf2hx2w45m1		 1	    3		  1
insert into t values(9969,‘test bind variable‘)    bfayz4q1j4b37		 1	    3		  1
insert into t values(9984,‘test bind variable‘)    48t1dy0tahgxh		 1	    3		  1
insert into t values(9998,‘test bind variable‘)    04bhmfjq8hhtu		 1	    3		  1
insert into t values(9967,‘test bind variable‘)    0njsupf834kn0		 1	    3		  1
insert into t values(9999,‘test bind variable‘)    6uhdudx8k4rv3		 1	    3		  1
insert into t values(9975,‘test bind variable‘)    0tqj0jcamsspu		 1	    3		  1
insert into t values(9957,‘test bind variable‘)    a6as35h2wwu00		 1	    3		  1
insert into t values(9970,‘test bind variable‘)    58m581pqq8v4j		 1	    3		  1
insert into t values(9982,‘test bind variable‘)    3gh1q9f2wnxr8		 1	    3		  1
insert into t values(9977,‘test bind variable‘)    1t0t0jz9y0zg9		 1	    3		  1
insert into t values(9988,‘test bind variable‘)    111vappsrszy7		 1	    3		  1
insert into t values(9994,‘test bind variable‘)    8kvjy7tns10vq		 1	    3		  1
insert into t values(9963,‘test bind variable‘)    c1w951tadx4tb		 1	    3		  1
insert into t values(9993,‘test bind variable‘)    10h1mbxvtt9tm		 1	    3		  1
insert into t values(9981,‘test bind variable‘)    gv77ng7kndhty		 1	    3		  1
insert into t values(9978,‘test bind variable‘)    0v7773365tj70		 1	    3		  1
insert into t values(9974,‘test bind variable‘)    astu71gzn1uw5		 1	    3		  1
insert into t values(9960,‘test bind variable‘)    09d0bxcsndxzm		 1	    3		  1
insert into t values(9959,‘test bind variable‘)    7ht6qzyy0jz5w		 1	    3		  1
insert into t values(9965,‘test bind variable‘)    dgz4fbhzgpzh4		 1	    3		  1
insert into t values(9989,‘test bind variable‘)    3srf852y19zx6		 1	    3		  1
insert into t values(9995,‘test bind variable‘)    1r6tp423v613x		 1	    3		  1
insert into t values(9976,‘test bind variable‘)    9vxdayk3yq1nn		 1	    3		  1
insert into t values(9958,‘test bind variable‘)    9ptg2jd30k6d8		 1	    3		  1
insert into t values(9968,‘test bind variable‘)    akt2u5gn1y9kp		 1	    3		  1
insert into t values(9992,‘test bind variable‘)    ch4rx2b3ja9x8		 1	    3		  1
insert into t values(9962,‘test bind variable‘)    a2p68fsk6abwz		 1	    3		  1
insert into t values(9997,‘test bind variable‘)    f0474tah8ubzq		 1	    3		  1
insert into t values(9972,‘test bind variable‘)    gzqpvbrsn6ggk		 1	    3		  1
insert into t values(9983,‘test bind variable‘)    ah9r6ghzsugmp		 1	    3		  1
insert into t values(9979,‘test bind variable‘)    2cvqu9h4wagva		 1	    3		  1
insert into t values(9996,‘test bind variable‘)    3h90mc46sqmzr		 1	    3		  1
insert into t values(9961,‘test bind variable‘)    7t8njvfx8fn4y		 1	    3		  1
insert into t values(9987,‘test bind variable‘)    1qxhj0g7cuw8u		 1	    3		  1
insert into t values(9991,‘test bind variable‘)    5n2jahrk5z258		 1	    3		  1
insert into t values(:"SYS_B_0",:"SYS_B_1")	   950r47takm3c4	      9953	    1		  1
insert into t values(9971,‘test bind variable‘)    fyb5pvjuqz4d0		 1	    3		  1
insert into t values(9955,‘test bind variable‘)    1adu3pctt76bp		 1	    3		  1
insert into t values(9990,‘test bind variable‘)    62pp4zqc9r767		 1	    3		  1
insert into t values(9973,‘test bind variable‘)    adb60k3nxr9mk		 1	    3		  1
insert into t values(9985,‘test bind variable‘)    gz4hry47rzhvt		 1	    3		  1
insert into t values(9986,‘test bind variable‘)    b54fdtcu47v0d		 1	    3		  1
insert into t values(9980,‘test bind variable‘)    fvwh43nh6zvhk		 1	    3		  1
insert into t values(9956,‘test bind variable‘)    1vcjq6rm9gx72		 1	    3		  1
insert into t values(9964,‘test bind variable‘)    a06un7tf1rxgu		 1	    3		  1
insert into t values(9954,‘test bind variable‘)    0nb4synx6bxqv		 1	    3		  1

48 rows selected.

SQL>

4. 再次清空shared_pool

SQL> alter system flush shared_pool;

System altered.

5. 将cursor_sharing改为SIMILAR,执行查询

SQL> alter session set cursor_sharing=similar;

Session altered.

Elapsed: 00:00:00.03
SQL> declare
begin
  for i in 1 .. 10000 loop
     execute immediate ‘insert into t values(‘||i||‘,‘‘test bind variable‘‘)‘;
  end loop;
  commit;
end;
/  2    3    4    5    6    7    8  

PL/SQL procedure successfully completed.

Elapsed: 00:00:01.14

5. 查看共享游标

SQL> SELECT sql_text,
       sql_id,
       EXECUTIONS,
       LOADS,
       VERSION_COUNT
  FROM v$sqlarea
 WHERE sql_text LIKE ‘insert into t%‘;  2    3    4    5    6    7  

SQL_TEXT					   SQL_ID		EXECUTIONS	LOADS VERSION_COUNT
-------------------------------------------------- -------------------- ---------- ---------- -------------
insert into t values(9966,‘test bind variable‘)    07xgdm0uwn5gb		 1	    4		  1
insert into t values(10000,‘test bind variable‘)   76rf2hx2w45m1		 1	    4		  1
insert into t values(9969,‘test bind variable‘)    bfayz4q1j4b37		 1	    4		  1
insert into t values(9984,‘test bind variable‘)    48t1dy0tahgxh		 1	    4		  1
insert into t values(9998,‘test bind variable‘)    04bhmfjq8hhtu		 1	    4		  1
insert into t values(9967,‘test bind variable‘)    0njsupf834kn0		 1	    4		  1
insert into t values(9999,‘test bind variable‘)    6uhdudx8k4rv3		 1	    4		  1
insert into t values(9975,‘test bind variable‘)    0tqj0jcamsspu		 1	    4		  1
insert into t values(9957,‘test bind variable‘)    a6as35h2wwu00		 1	    4		  1
insert into t values(9970,‘test bind variable‘)    58m581pqq8v4j		 1	    4		  1
insert into t values(9982,‘test bind variable‘)    3gh1q9f2wnxr8		 1	    4		  1
insert into t values(9977,‘test bind variable‘)    1t0t0jz9y0zg9		 1	    4		  1
insert into t values(9988,‘test bind variable‘)    111vappsrszy7		 1	    4		  1
insert into t values(9994,‘test bind variable‘)    8kvjy7tns10vq		 1	    4		  1
insert into t values(9963,‘test bind variable‘)    c1w951tadx4tb		 1	    4		  1
insert into t values(9993,‘test bind variable‘)    10h1mbxvtt9tm		 1	    4		  1
insert into t values(9981,‘test bind variable‘)    gv77ng7kndhty		 1	    4		  1
insert into t values(9978,‘test bind variable‘)    0v7773365tj70		 1	    4		  1
insert into t values(9974,‘test bind variable‘)    astu71gzn1uw5		 1	    4		  1
insert into t values(9960,‘test bind variable‘)    09d0bxcsndxzm		 1	    4		  1
insert into t values(9959,‘test bind variable‘)    7ht6qzyy0jz5w		 1	    4		  1
insert into t values(9965,‘test bind variable‘)    dgz4fbhzgpzh4		 1	    4		  1
insert into t values(9989,‘test bind variable‘)    3srf852y19zx6		 1	    4		  1
insert into t values(9995,‘test bind variable‘)    1r6tp423v613x		 1	    4		  1
insert into t values(9976,‘test bind variable‘)    9vxdayk3yq1nn		 1	    4		  1
insert into t values(9958,‘test bind variable‘)    9ptg2jd30k6d8		 1	    4		  1
insert into t values(9968,‘test bind variable‘)    akt2u5gn1y9kp		 1	    4		  1
insert into t values(9992,‘test bind variable‘)    ch4rx2b3ja9x8		 1	    4		  1
insert into t values(9962,‘test bind variable‘)    a2p68fsk6abwz		 1	    4		  1
insert into t values(9997,‘test bind variable‘)    f0474tah8ubzq		 1	    4		  1
insert into t values(9972,‘test bind variable‘)    gzqpvbrsn6ggk		 1	    4		  1
insert into t values(9983,‘test bind variable‘)    ah9r6ghzsugmp		 1	    4		  1
insert into t values(9979,‘test bind variable‘)    2cvqu9h4wagva		 1	    4		  1
insert into t values(9996,‘test bind variable‘)    3h90mc46sqmzr		 1	    4		  1
insert into t values(9961,‘test bind variable‘)    7t8njvfx8fn4y		 1	    4		  1
insert into t values(9987,‘test bind variable‘)    1qxhj0g7cuw8u		 1	    4		  1
insert into t values(9991,‘test bind variable‘)    5n2jahrk5z258		 1	    4		  1
insert into t values(:"SYS_B_0",:"SYS_B_1")	   950r47takm3c4	      9953	    1		  1
insert into t values(9971,‘test bind variable‘)    fyb5pvjuqz4d0		 1	    4		  1
insert into t values(9955,‘test bind variable‘)    1adu3pctt76bp		 1	    4		  1
insert into t values(9990,‘test bind variable‘)    62pp4zqc9r767		 1	    4		  1
insert into t values(9973,‘test bind variable‘)    adb60k3nxr9mk		 1	    4		  1
insert into t values(9985,‘test bind variable‘)    gz4hry47rzhvt		 1	    4		  1
insert into t values(9986,‘test bind variable‘)    b54fdtcu47v0d		 1	    4		  1
insert into t values(9980,‘test bind variable‘)    fvwh43nh6zvhk		 1	    4		  1
insert into t values(9956,‘test bind variable‘)    1vcjq6rm9gx72		 1	    4		  1
insert into t values(9964,‘test bind variable‘)    a06un7tf1rxgu		 1	    4		  1
insert into t values(9954,‘test bind variable‘)    0nb4synx6bxqv		 1	    4		  1

48 rows selected.

和cursor_sharing=FORCE时,情况一样。

这两种方法都不推荐使用,有bug 。建议规范前台业务查询,尽量使用绑定变量。

时间: 2024-12-23 15:23:14

Oracle 学习之性能优化(三)绑定变量的相关文章

Oracle 学习之性能优化(八)优化器

 我们知道,在sql语句解析的过程中,有一个过程叫优化.Oracle中有一个叫优化器的组件,专门来处理sql的优化.在考虑查询条件和对象引用的许多相关因素后,优化器能确定出执行SQL语句最有效的方式来.对于任何SQL语句,优化器优化的结果,可以极大地影响执行时间. Oracle优化器的优化方法有两种: CBO 基于成本的优化法则 RBO 基于规则的优化法则 初始化参数optimizer_mode控制着优化器优化的行为 SQL> show parameter optimizer_mode NAME

Oracle 学习之 性能优化(十三) 索引

一.索引概念 索引是一种供服务器在表中快速查找一个行的数据库结构.合理使用索引能够大大提高数据库的运行效率. 在数据库中建立索引主要有以下作用. (1)快速存取数据. (2)既可以改善数据库性能,又可以保证列值的唯一性. (3)实现表与表之间的参照完整性 (4)在使用order by.group by子句进行数据检索时,利用索引可以减少排序和分组的时间. 在关系数据库中,每一行都由一个行唯一标识RowID.RowID包括该行所在的文件.在文件中的块数和块中的行号.索引中包含一个索引条目,每一个索

Oracle 学习之性能优化(五)执行计划

读懂执行计划有什么用呢? 执行计划贯穿Oracle调优始终. 了解执行计划的真实执行过程,将有助于优化. 对亍Oracle的原理理解有一定帮助. 读懂执行计划,SQL调优的第一步. 什么是SQL Execution Plan执行计划? SQL是声明型语言,她只说我要去哪里,但很少告诉你到底如何去? SQL语句的执行最终会落实为Oracle执行步骤的组合 =>[SQL执行计划] 查看执行计划的方法 SQLPLUS AUTOTRACE Explain Plan For SQL SQL_TRACE 使

Oracle 学习之 性能优化(十五) ASH、ADDM、AWR

ASH(Active Session History) ASH以V$SESSION为基础,每秒采样一次,记录活动会话等待的事件.不活动的会话不会采样,采样工作由新引入的后台进程MMNL来完成.ASH buffers 的最小值为1MB,最大值不超过30MB.内存中记录数据.期望值是记录一小时的内容. AWR(Automatic Workload Repository) 自动工作负载信息库 ASH 内存记录数据始终是有限的,为了保存历史数据,引入了自动负载信息库(AutomaticWorkload

Oracle 学习之性能优化(一)SQL语句处理

当向Oracle提交一个sql命令时,Oracle到底做了哪些事情?对这个问题有很好的理解,能帮助你更好的分析sql语句的优化. 执行一条sql语句从开始到结束,需要经历4个步骤: 分析--对提交的语句进行语法分析.语义分析和共享池检查. 优化--生成一个可在数据库中用来执行语句的最佳计划 行资源生成--为会话取得最佳计划并建立执行计划 语句执行--完成实际执行查询的行资源生成步骤的输出.对应DDL来说,这一步就是语句的结   束.对应SELECT来说,这一步是取数据的开始. 以上步骤,有的是可

Oracle 学习之性能优化(九)使用hint

基于代价的优化器是很聪明的,在绝大多数情况下它会选择正确的优化器,减轻了DBA的负担.但有时它也聪明反被聪明误,选择了很差的执行计划,使某个语句的执行变得奇慢无比.此时就需要DBA进行人为的干预,告诉优化器使用我们指定的存取路径或连接类型生成执行计划,从 而使语句高效的运行.例如,如果我们认为对于一个特定的语句,执行全表扫描要比执行索引扫描更有效,则我们就可以指示优化器使用全表扫描.在Oracle 中,是通过为语句添加 Hints(提示)来实现干预优化器优化的目的. 不建议在代码中使用hint,

Oracle 学习之 性能优化(十二) 分区表

一.分区概念 Oracle允许将表.索引.索引组织表细分成更小的片,每个片我们称之为分区.分区有其自己的名字和存储参数. 如下图: 每行数据只能属于一个分区,分区键决定数据行属于哪个分区.分区键由一个或多个列组成.Oracle自动的将数据的DML操作映射到相应的分区中. 何时使用分区表: Tables greater than 2 GB should always be considered as candidates for partitioning. Tables containing hi

Oracle 学习之性能优化(六)访问路径

访问路径是指Oracle找到用户需要的数据的方法,这些方法很少,包括: 声名狼藉的全表扫描--人们不惜一切视图避免的(曲解的)访问路径. 各种类型的索引扫描--这是人们感觉良好的访问路径(多数情况下是被曲解的). 通过hash或者rowid的方式直接访问,通常对于单数据行来说,是最快的. 并没有一种访问路径是最好的,如果有,那么Oracle只需提供这一种访问路径就好了. 全表扫描 全扫描就是顺序的读取表中的所有数据块.采用多块读的方式,从头开始扫描表中的块,直到高水位线.全扫描是处理大数据量行之

Oracle 学习之性能优化(七)join的实现方式

本文讨论一下join技术背后的机制.我们知道常用的表连接有如下几种 笛卡尔连接 内连接 左外连接 右外连接 全连接 这些sql的写法,想必大家都很清楚了,那么这些连接的数据访问是如何实现的呢? nested loop 我们看如下查询 SQL> alter session set optimizer_mode=rule; Session altered. SQL> select ename,dname from emp,dept where emp.deptno=dept.deptno; 14