Oracle 变量绑定与变量窥视合集系列一

简介:

Oracle 变量绑定与变量窥视合集》

数据库环境

LEO1@LEO1> select * from v$version;

BANNER

--------------------------------------------------------------------------------

Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production

PL/SQL Release 11.2.0.1.0 - Production

CORE    11.2.0.1.0      Production

TNS for Linux: Version 11.2.0.1.0 - Production

NLSRTL Version 11.2.0.1.0 - Production


 

 用示例说明绑定变量的应用领域是OLTP而不是OLAP

变量绑定:这是一个老生常谈的话题,我所理解的绑定就是执行计划的绑定,我所理解的变量就是谓词替换的变量。

变量绑定机制:要说机制不得不说一下SQL执行的过程,三部曲:解析 –> 执行 -> 取操作,而绑定变量就发生在解析这一步,而解析又分成硬解析和软解析。

硬解析:当一条SQL语句第一次执行时,首先生成执行计划,并把这个执行计划存放到shared_poollibrary cache中,这个过程叫做硬解析。

软解析:如果SQL语句已经被硬解析过了,那么可以直接从library cache中抽取现成的执行计划来重用,这个过程叫做软解析,目的减少生成执行计划这方面的资源消耗。为什么这么说呢,硬解析会消耗一些系统资源,尤其是CPU的资源,从而影响系统的效率,如果能把这方面的影响消除,那么对系统当然是多多益善了,哈 多侃了几句。

SQL详细执行过程:当oracle接收到一条sql语句时,首先会把这条sql语句字符做成哈希值,然后到library cache中寻找是否有和这个哈希值相匹配的sql存在,如果有就直接使用这个sql的执行计划去执行当前的sql语句,最后将结果返回给用户。如果没有找到相同的哈希值,oracle会认为这是一条新的sql,将会重新生成执行计划来执行(在这个过程中先要检查语法分析和语义分析),最后将结果返回给用户。

实验

下面我们演示一下绑定变量和非绑定变量在资源消耗上的差异

LEO1@LEO1> drop table leo1 purge;                清理环境

Table dropped.

LEO1@LEO1> drop table leo2 purge;               

Table dropped.

LEO1@LEO1> create table leo1 as select * from dba_objects;    创建leo1

Table created.

LEO1@LEO1> create table leo2 as select * from dba_objects;    创建leo2

Table created.

LEO1@LEO1> alter session set tracefile_identifier='bind_variable';    设置trace文件标识

Session altered.

LEO1@LEO1> alter session set sql_trace=true;      启动trace功能,追踪sql资源消耗情况

Session altered.

LEO1@LEO1> begin

for i in 1..100 loop

execute immediate 'select * from leo1 where object_id=:i' using i;

end loop;

end;

/

PL/SQL procedure successfully completed.

我们对一条sql执行了100次并采用了绑定变量技术,oracle对这条sql只有一次硬解析,没有软解析,反复执行100次。

LEO1@LEO1> alter session set sql_trace=false;           关闭trace功能

Session altered.

LEO1@LEO1> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select * from leo1 where %';

SQL_TEXT                             PARSE_CALLS  LOADS   EXECUTIONS

-------------------------------------------------- ----------- -------------------------- ----------- ---------- ------------------

select * from leo1 where object_id=:i         1          1        100

SQL_TEXT:我们跟踪的sql语句

PARSE_CALLS:硬解析+软解析次数       1   只有硬解析没有软解析

LOADS:硬解析次数                    1

EXECUTIONS:执行次数                 100

虽说值隐藏在变量中,但在解析环节oracle认为是一样的

[oracle@leonarding1 trace]$ tkprof LEO1_ora_16433_bind_variable.trc bind_variable.txt sys=no

TKPROF: Release 11.2.0.1.0 - Development on Fri Feb 1 13:18:08 2013

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

使用tkprof工具过滤和汇总trace文件的,sys=no 不输出sys用户递归语句,默认yes,实际上设置成no更具有可读性

--------- 下面是bind_variable.txt文件信息

********************************************************************************

SQL ID: 0b74y9utb0b6r             #这就是SQL语句字符的哈希值

Plan Hash: 2716644435

select *

from

leo1 where object_id=:i

call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        1      0.00       0.00          0          0          0           0

Execute    100      0.01       0.01          0          1          0           0

Fetch        0      0.00       0.00          0          0          0           0

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total      101      0.01       0.01          0          1          0           0

Misses in library cache during parse: 1        只有1次硬解析,反复执行100

Optimizer mode: ALL_ROWS

Parsing user id: 85     (recursive depth: 1)

Rows     Row Source Operation

-------  ---------------------------------------------------

      0  TABLE ACCESS FULL LEO1 (cr=0 pr=0 pw=0 time=0 us cost=288 size=2484 card=12)

********************************************************************************

下面是一个非绑定变量的sql执行情况

LEO1@LEO1> alter session set sql_trace=true;              启动trace功能

Session altered.

LEO1@LEO1> begin

for i in 1..100 loop

execute immediate 'select * from leo2 where object_id='||i;

end loop;

end;

/

PL/SQL procedure successfully completed.

我们对一条sql执行了100次没有采用绑定变量技术,oracle对这条sql要硬解析100次,执行100次,资源严重被sql解析所消耗,系统显得缓慢不堪。

LEO1@LEO1> alter session set sql_trace=false;             关闭trace功能

Session altered.

LEO1@LEO1> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select * from leo2 where %' order by 1;

SQL_TEXT                                           PARSE_CALLS      LOADS EXECUTIONS

-------------------------------------------------- ----------- ---------- ----------

select * from leo2 where object_id=1                         1          1          1

select * from leo2 where object_id=10                        1          1          1

select * from leo2 where object_id=100                       1          1          1

select * from leo2 where object_id=11                        1          1          1

select * from leo2 where object_id=12                        1          1          1

select * from leo2 where object_id=13                        1          1          1

select * from leo2 where object_id=14                        1          1          1

select * from leo2 where object_id=15                        1          1          1

select * from leo2 where object_id=16                        1          1          1

select * from leo2 where object_id=17                        1          1          1

select * from leo2 where object_id=18                        1          1          1

select * from leo2 where object_id=19                        1          1          1

select * from leo2 where object_id=2                         1          1          1

select * from leo2 where object_id=20                        1          1          1

select * from leo2 where object_id=21                        1          1          1

select * from leo2 where object_id=22                        1          1          1

select * from leo2 where object_id=23                        1          1          1

select * from leo2 where object_id=24                        1          1          1

select * from leo2 where object_id=25                        1          1          1

select * from leo2 where object_id=26                        1          1          1

select * from leo2 where object_id=27                        1          1          1

select * from leo2 where object_id=28                        1          1          1

select * from leo2 where object_id=29                        1          1          1

select * from leo2 where object_id=3                         1          1          1

select * from leo2 where object_id=30                        1          1          1

select * from leo2 where object_id=31                        1          1          1

select * from leo2 where object_id=32                        1          1          1

select * from leo2 where object_id=33                        1          1          1

select * from leo2 where object_id=34                        1          1          1

select * from leo2 where object_id=35                        1          1          1

select * from leo2 where object_id=36                        1          1          1

select * from leo2 where object_id=37                        1          1          1

select * from leo2 where object_id=38                        1          1          1

select * from leo2 where object_id=39                        1          1          1

select * from leo2 where object_id=4                         1          1          1

select * from leo2 where object_id=40                        1          1          1

select * from leo2 where object_id=41                        1          1          1

select * from leo2 where object_id=42                        1          1          1

select * from leo2 where object_id=43                        1          1          1

select * from leo2 where object_id=44                        1          1          1

select * from leo2 where object_id=45                        1          1          1

select * from leo2 where object_id=46                        1          1          1

select * from leo2 where object_id=47                        1          1          1

select * from leo2 where object_id=48                        1          1          1

select * from leo2 where object_id=49                        1          1          1

select * from leo2 where object_id=5                         1          1          1

select * from leo2 where object_id=50                        1          1          1

select * from leo2 where object_id=51                        1          1          1

select * from leo2 where object_id=52                        1          1          1

select * from leo2 where object_id=53                        1          1          1

select * from leo2 where object_id=54                        1          1          1

select * from leo2 where object_id=55                        1          1          1

select * from leo2 where object_id=56                        1          1          1

select * from leo2 where object_id=57                        1          1          1

select * from leo2 where object_id=58                        1          1          1

select * from leo2 where object_id=59                        1          1          1

select * from leo2 where object_id=6                         1          1          1

select * from leo2 where object_id=60                        1          1          1

select * from leo2 where object_id=61                        1          1          1

select * from leo2 where object_id=62                        1          1          1

select * from leo2 where object_id=63                        1          1          1

select * from leo2 where object_id=64                        1          1          1

select * from leo2 where object_id=65                        1          1          1

select * from leo2 where object_id=66                        1          1          1

select * from leo2 where object_id=67                        1          1          1

select * from leo2 where object_id=68                        1          1          1

select * from leo2 where object_id=69                        1          1          1

select * from leo2 where object_id=7                         1          1          1

select * from leo2 where object_id=70                        1          1          1

select * from leo2 where object_id=71                        1          1          1

select * from leo2 where object_id=72                        1          1          1

select * from leo2 where object_id=73                        1          1          1

select * from leo2 where object_id=74                        1          1          1

select * from leo2 where object_id=75                        1          1          1

select * from leo2 where object_id=76                        1          1          1

select * from leo2 where object_id=77                        1          1          1

select * from leo2 where object_id=78                        1          1          1

select * from leo2 where object_id=79                        1          1          1

select * from leo2 where object_id=8                         1          1          1

select * from leo2 where object_id=80                        1          1          1

select * from leo2 where object_id=81                        1          1          1

select * from leo2 where object_id=82                        1          1          1

select * from leo2 where object_id=83                        1          1          1

select * from leo2 where object_id=84                        1          1          1

select * from leo2 where object_id=85                        1          1          1

select * from leo2 where object_id=86                        1          1          1

select * from leo2 where object_id=87                        1          1          1

select * from leo2 where object_id=88                        1          1          1

select * from leo2 where object_id=89                        1          1          1

select * from leo2 where object_id=9                         1          1          1

select * from leo2 where object_id=90                        1          1          1

select * from leo2 where object_id=91                        1          1          1

select * from leo2 where object_id=92                        1          1          1

select * from leo2 where object_id=93                        1          1          1

select * from leo2 where object_id=94                        1          1          1

select * from leo2 where object_id=95                        1          1          1

select * from leo2 where object_id=96                        1          1          1

select * from leo2 where object_id=97                        1          1          1

select * from leo2 where object_id=98                        1          1          1

select * from leo2 where object_id=99                        1          1          1

100 rows selected.

我们从动态性能视图上可以看出oracle每执行一次sql,都要先硬解析1次之后在执行。这种没有使用绑定变量技术在硬解析消耗上就比使用绑定变量技术多损耗100倍,如果执行的次数上万 上亿对系统性能的影响可想而知。

--------- 我们来看看trace文件的内容

[oracle@leonarding1 trace]$ tkprof LEO1_ora_16433_bind_variable.trc bind_variable.txt sys=no

TKPROF: Release 11.2.0.1.0 - Development on Fri Feb 1 13:49:52 2013

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.

********************************************************************************

SQL ID: 22r47f3t6w0td

Plan Hash: 2258638698

select *

from

leo2 where object_id=1

call     count       cpu    elapsed       disk      query    current        rows

------- ------  -------- ---------- ---------- ---------- ----------  ----------

Parse        1      0.00       0.00          0          1          0           0

Execute      1      0.00       0.00          0          0          0           0

Fetch        0      0.00       0.00          0          0          0           0

------- ------  -------- ---------- ---------- ---------- ----------  ----------

total        2      0.00       0.00          0          1          0           0

Misses in library cache during parse: 1

Optimizer mode: ALL_ROWS

Parsing user id: 85     (recursive depth: 1)

Rows     Row Source Operation

-------  ---------------------------------------------------

      0  TABLE ACCESS FULL LEO2 (cr=0 pr=0 pw=0 time=0 us cost=288 size=2484 card=12)

********************************************************************************

SQL ID: 9nb3n54fy0z8m

Plan Hash: 2258638698

select *

from

leo2 where object_id=2

********************************************************************************

SQL ID: 8mc705qymd7qs

Plan Hash: 2258638698

select *

from

leo2 where object_id=3

如上所示每个sql语句的SQL_ID都是不一样的,都是相对独立的,因此每执行1次就要解析1次,两种情况对比结果显示,绑定变量要比没有绑定变量消耗的资源少的少,sql执行的次数越多,这种效果越明显。所以我们说绑定变量本质就是用一个变量来代替谓词常量,让oracle只需要硬解析一次,后续sql都直接使用之前执行计划来执行,这样就省却了很消耗资源的硬解析过程

下面讨论绑定变量为什么适合于OLTP而不是OLAP

OLTP

1.适合OLTP系统架构

2.SQL简单非常相似,结果集非常小,例如 只有谓词部分不同,余下部分全部相同的SQL语句,这种情况下执行计划都是一样的,在执行计划几乎不变的情况下,oracle使用变量来代替谓词常量,使用同一个执行计划是非常合理的

3.SQL重复率很高,或者只有谓词条件不同而已

4.DML操作频繁

5.SQL语句执行条数多,条数越多减少硬解析越有意义

6.基于主键做查询,还有等值查询,唯一性查询,这类查询相对适合绑定变量

select   *   from  leonarding   where   id=:leo;

 

OLAP

1.不适合OLAP系统架构

2.SQL的执行计划多变,会因为值的不同导致执行计划的不同,可能第一次执行是一种执行计划,第二次执行是另一种执行计划,所以不适合进行绑定变量操作,会让oracle盲目浪费大量资源消耗,SQL语句即使只有谓词条件不同,oracle应然可能采取不同的执行计划。

3.SQL重复率较低,大部分都是批量加载批量检索的操作

4.数据聚合操作频繁

5.SQL语句执行条数少,SQL硬解析对系统性能影响较小,绑定没有意义

6.分区表相对不太适合绑定变量技术


 本文转自 leonarding151CTO博客,原文链接:http://blog.51cto.com/leonarding/1131507,如需转载请自行联系原作者


相关实践学习
数据库实验室挑战任务-初级任务
本场景介绍如何开通属于你的免费云数据库,在RDS-MySQL中完成对学生成绩的详情查询,执行指定类型SQL。
阿里云云原生数据仓库AnalyticDB MySQL版 使用教程
云原生数据仓库AnalyticDB MySQL版是一种支持高并发低延时查询的新一代云原生数据仓库,高度兼容MySQL协议以及SQL:92、SQL:99、SQL:2003标准,可以对海量数据进行即时的多维分析透视和业务探索,快速构建企业云上数据仓库。 了解产品 https://www.aliyun.com/product/ApsaraDB/ads
相关文章
|
20天前
|
SQL 存储 Oracle
Oracle的PL/SQL定义变量和常量:数据的稳定与灵动
【4月更文挑战第19天】在Oracle PL/SQL中,变量和常量扮演着数据存储的关键角色。变量是可变的“魔术盒”,用于存储程序运行时的动态数据,通过`DECLARE`定义,可在循环和条件判断中体现其灵活性。常量则是不可变的“固定牌”,一旦设定值便保持不变,用`CONSTANT`声明,提供程序稳定性和易维护性。通过 `%TYPE`、`NOT NULL`等特性,可以更高效地管理和控制变量与常量,提升代码质量。善用两者,能优化PL/SQL程序的结构和性能。
|
3月前
|
Oracle 关系型数据库 数据库
Flink Sink to Oracle 存在字段CLOB类型,如何处理错误”ORA-01461: 仅能绑定要插入LONG的LONG值“
做Flink CDC同步数据过程中,目标是Oracle数据库,其中某个字段较大被设置为CLOB类型,其中会遇到异常,”ORA-01461: 仅能绑定要插入LONG的LONG值“
|
11月前
|
SQL 缓存 监控
为什么Oracle中包含绑定变量的SQL会有多个游标?(译文)
为了改进包含绑定变量的SQL的执行计划,Oracle在11g版本中引入了一项名为自适应游标共享(ACS,Adaptive Cursor Sharing)的新功能。
109 0
|
12月前
|
SQL Oracle 关系型数据库
Oracle优化09-绑定变量
Oracle优化09-绑定变量
187 0
|
12月前
|
SQL 缓存 Oracle
Oracle-绑定变量binding variable解读
Oracle-绑定变量binding variable解读
275 0
|
SQL 监控 Oracle
Oracle数据库---怎样获得sql语句执行时的绑定变量
绑定变量是oracle常用的优化技术,有时候我们需要获得sql运行时绑定变量的值,用10046事件跟踪会话即可获得
463 0
|
SQL Oracle 关系型数据库
PLSQL_性能优化系列19_Oracle Explain Plan解析计划通过Profile绑定
20150529 Created By BaoXinjian   一、摘要   1. 应用场景 当运行很久的Job突然出现性能问题时,并排除数据量突然变大,可能原因有执行的脚本的某些对应的SQL的解析计划变更,在Oracle 10g中可以通过绑定profile,在11g中可以通过baseline进行绑定 2.
787 0