wskickahn 发表于 2018-9-23 06:06:28

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

《Oracle 变量绑定与变量窥视合集》
数据库环境
LEO1@LEO1> select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition>
PL/SQL>
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_pool的library 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>>
Session>
LEO1@LEO1>>
Session>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>>
Session>LEO1@LEO1> select sql_text,parse_calls,loads,executions from v$sql where sql_text like 'select * from leo1 where %';
SQL_TEXT                           PARSE_CALLSLOADS   EXECUTIONS
-------------------------------------------------- ----------- -------------------------- ----------- ---------- ------------------
select * from leo1 where object_id=:i         1          1      100
SQL_TEXT:我们跟踪的sql语句
PARSE_CALLS:硬解析+软解析次数       1次   只有硬解析没有软解析
LOADS:硬解析次数                  1次
EXECUTIONS:执行次数               100次
虽说值隐藏在变量中,但在解析环节oracle认为是一样的
$ tkprof LEO1_ora_16433_bind_variable.trc bind_variable.txt sys=no

TKPROF:>Copyright (c) 1982, 2009, Oracle and/or its affiliates.All rights reserved.
使用tkprof工具过滤和汇总trace文件的,sys=no 不输出sys用户递归语句,默认yes,实际上设置成no更具有可读性
--------- 下面是bind_variable.txt文件信息
********************************************************************************

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>Rows   Row Source Operation
----------------------------------------------------------

      0TABLE ACCESS FULL LEO1 (cr=0 pr=0 pw=0 time=0 us cost=288>********************************************************************************
下面是一个非绑定变量的sql执行情况

LEO1@LEO1>>
Session>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>>
Session>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文件的内容
$ tkprof LEO1_ora_16433_bind_variable.trc bind_variable.txt sys=no

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

SQL>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>Rows   Row Source Operation
----------------------------------------------------------

      0TABLE ACCESS FULL LEO2 (cr=0 pr=0 pw=0 time=0 us cost=288>********************************************************************************

SQL>Plan Hash: 2258638698
select *
from
leo2 where object_id=2
********************************************************************************

SQL>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   *   fromleonarding   where   id=:leo;
OLAP
1.不适合OLAP系统架构
2.SQL的执行计划多变,会因为值的不同导致执行计划的不同,可能第一次执行是一种执行计划,第二次执行是另一种执行计划,所以不适合进行绑定变量操作,会让oracle盲目浪费大量资源消耗,SQL语句即使只有谓词条件不同,oracle应然可能采取不同的执行计划。
3.SQL重复率较低,大部分都是批量加载批量检索的操作
4.数据聚合操作频繁
5.SQL语句执行条数少,SQL硬解析对系统性能影响较小,绑定没有意义
6.分区表相对不太适合绑定变量技术

页: [1]
查看完整版本: Oracle 变量绑定与变量窥视合集系列一