Oracle 硬解析与软解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: --=======================-- Oracle 硬解析与软解析--=======================     Oracle 硬解析与软解析是我们经常遇到的问题,什么情况会产生硬解析,什么情况产生软解析,又当如何避免硬解析?下面的描述将给出软硬解析的产生,以及硬解析的弊端和如何避免硬解析的产生。

--=======================

-- Oracle 硬解析与软解析

--=======================

 

    Oracle 硬解析与软解析是我们经常遇到的问题,什么情况会产生硬解析,什么情况产生软解析,又当如何避免硬解析?下面的描述将给出

软硬解析的产生,以及硬解析的弊端和如何避免硬解析的产生。

   

一、SQL语句的执行过程

    当发布一条SQLPL/SQL命令时,Oracle会自动寻找该命令是否存在于共享池中来决定对当前的语句使用硬解析或软解析。

    通常情况下,SQL语句的执行过程如下:

    a.SQL代码的语法(语法的正确性)及语义检查(对象的存在性与权限)

    b.SQL代码的文本进行哈希得到哈希值。

    c.如果共享池中存在相同的哈希值,则对这个命令进一步判断是否进行软解析,否则到e步骤。

    d.对于存在相同哈希值的新命令行,其文本将与已存在的命令行的文本逐个进行比较。这些比较包括大小写,字符串是否一致,空格,注释

        等,如果一致,则对其进行软解析,转到步骤f否则到d步骤红色字体描述有误应该转到步骤e(更正@20130905,谢网友keaihuilang指出)

    e.硬解析,生成执行计划。

    f.执行SQL代码,返回结果。

 

二、不能使用软解析的情形   

    1.下面的三个查询语句,不能使用相同的共享SQL区。尽管查询的表对象使用了大小写,但Oracle为其生成了不同的执行计划

        select * from emp;

        select * from Emp;

        select * from EMP;

    2.类似的情况,下面的查询中,尽管其where子句empno的值不同,Oracle同样为其生成了不同的执行计划

        select * from emp where empno=7369

        select * from emp where empno=7788

 

    3.在判断是否使用硬解析时,所参照的对象及schema应该是相同的,如果对象相同,而schema不同,则需要使用硬解析,生成不同的执行计划

        sys@ASMDB> select owner,table_name from dba_tables where table_name like 'TB_OBJ%';

 

        OWNER                          TABLE_NAME

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

        USR1                           TB_OBJ               --两个对象的名字相同,当所有者不同

        SCOTT                          TB_OBJ

 

        usr1@ASMDB> select * from tb_obj;

 

        scott@ASMDB> select * from tb_obj;      --此时两者都需要使用硬解析以及走不同的执行计划

 

三、硬解析的弊端

        硬解析即整个SQL语句的执行需要完完全全的解析,生成执行计划。而硬解析,生成执行计划需要耗用CPU资源,以及SGA资源。在此不

    得不提的是对库缓存中闩的使用。闩是锁的细化,可以理解为是一种轻量级的串行化设备。当进程申请到闩后,则这些闩用于保护共享内存

    的数在同一时刻不会被两个以上的进程修改。在硬解析时,需要申请闩的使用,而闩的数量在有限的情况下需要等待。大量的闩的使用由此

    造成需要使用闩的进程排队越频繁,性能则逾低下。

       

四、硬解析的演示       

    下面对上面的两种情形进行演示

    在两个不同的session中完成,一个为sys帐户的session,一个为scott账户的session,不同的session,其SQL命令行以不同的帐户名开头

    " sys@ASMDB> "  表示使用时sys帐户的session" scott@ASMDB> "表示scott帐户的session

 

        sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;        

 

        NAME                      CLASS      VALUE

        -------------------- ---------- ----------           --当前的硬解析值为569

        parse count (hard)           64        569

 

        scott@ASMDB> select * from emp;   

 

        sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;     

 

        NAME                      CLASS      VALUE

        -------------------- ---------- ----------           --执行上一个查询后硬解析值为570,解析次数增加了一次

        parse count (hard)           64        570

 

        scott@ASMDB> select * from Emp;

 

        sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;       

 

        NAME                      CLASS      VALUE

        -------------------- ---------- ----------           --执行上一个查询后硬解析值为571

        parse count (hard)           64        571

 

        scott@ASMDB> select * from EMP;

 

        sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;       

 

        NAME                      CLASS      VALUE

        -------------------- ---------- ----------           --执行上一个查询后硬解析值为572

        parse count (hard)           64        572  

 

        scott@ASMDB> select * from emp where empno=7369;      

 

        sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;

 

        NAME                      CLASS      VALUE

        -------------------- ---------- ----------           --执行上一个查询后硬解析值为573

        parse count (hard)           64        573

 

        scott@ASMDB> select * from emp where empno=7788;   --此处原来empno=7369,复制错误所致,现已更正为7788@20130905  

 

        sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;

 

        NAME                      CLASS      VALUE

        -------------------- ---------- ----------          --执行上一个查询后硬解析值为574

        parse count (hard)           64        574

 

    从上面的示例中可以看出,尽管执行的语句存在细微的差别,但Oracle还是为其进行了硬解析,生成了不同的执行计划。即便是同样的SQL

    语句,而两条语句中空格的多少不一样,Oracle同样会进行硬解析。

 

五、编码硬解析的改进方法

    1.更改参数cursor_sharing

        参数cursor_sharing决定了何种类型的SQL能够使用相同的SQL area

        CURSOR_SHARING = { SIMILAR | EXACT | FORCE }   

            EXACT      --只有当发布的SQL语句与缓存中的语句完全相同时才用已有的执行计划。

            FORCE      --如果SQL语句是字面量,则迫使Optimizer始终使用已有的执行计划,无论已有的执行计划是不是最佳的。

            SIMILAR    --如果SQL语句是字面量,则只有当已有的执行计划是最佳时才使用它,如果已有执行计划不是最佳则重新对这个SQL

                       --语句进行分析来制定最佳执行计划。

        可以基于不同的级别来设定该参数,如ALTER SESSION, ALTER SYSTEM

 

            sys@ASMDB> show parameter cursor_shar             --查看参数cursor_sharing

 

            NAME                                 TYPE        VALUE

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

            cursor_sharing                       string      EXACT

 

            sys@ASMDB> alter system set cursor_sharing='similar';    --将参数cursor_sharing的值更改为similar

 

            sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;   

 

            NAME                      CLASS      VALUE

            -------------------- ---------- ----------        --当前硬解析的值为865

            parse count (hard)           64        865

 

            scott@ASMDB> select * from dept where deptno=10;

           

            sys@ASMDB> select name,class,value from v$sysstat where statistic#=331; 

 

            NAME                      CLASS      VALUE

            -------------------- ---------- ----------        --执行上一条SQL查询后,硬解析的值变为866

            parse count (hard)           64        866

 

            scott@ASMDB> select * from dept where deptno=20;

 

            sys@ASMDB> select name,class,value from v$sysstat where statistic#=331;

 

            NAME                      CLASS      VALUE

            -------------------- ---------- ----------        --执行上一条SQL查询后,硬解析的值没有发生变化还是866

            parse count (hard)           64        866

 

            sys@ASMDB> select sql_text,child_number from v$sql   -- 在下面的结果中可以看到SQL_TEXT列中使用了绑定变量:"SYS_B_0"

              2  where sql_text like 'select * from dept where deptno%';

 

            SQL_TEXT                                           CHILD_NUMBER

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

            select * from dept where deptno=:"SYS_B_0"                    0

 

            sys@ASMDB> alter system set cursor_sharing='exact';       --cursor_sharing改回为exact

 

            --接下来在scottsession 中执行deptno=40 和的查询后再查看sql_text,当cursor_sharing改为exact后,每执行那个一次

            --也会在v$sql中增加一条语句

 

            sys@ASMDB> select sql_text,child_number from v$sql               

              2  where sql_text like 'select * from dept where deptno%';

 

            SQL_TEXT                                           CHILD_NUMBER

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

            select * from dept where deptno=50                            0     

            select * from dept where deptno=40                            0

            select * from dept where deptno=:"SYS_B_0"                    0

 

        注意当该参数设置为similar,会产生不利的影响,可以参考这里:cursor_sharing于expdp

 

    2.使用绑定变量

        绑定变量要求变量名称,数据类型以及长度是一致,否则无法使用软解析

        绑定变量(bind variable)是指在DML语句中使用一个占位符,即使用冒号后面紧跟变量名的形式,如下

            select * from emp where empno=7788    --未使用绑定变量

            select * from emp where empono=:eno   --:eno即为绑定变量

        在第二个查询中,变量值在查询执行时被提供。该查询只编译一次,随后会把查询计划存储在一个共享池(库缓存)中,以便以后获取

            和重用这个查询计划。

   

        下面使用了绑定变量,但两个变量其实质是不相同的,对这种情形,同样使用硬解析

            select * from emp where empno=:eno;

            select * from emp where empno=:emp_no

 

        使用绑定变量时要求不同的会话中使用了相同的回话环境,以及优化器的规则等。

 

        使用绑定变量的例子(参照了TOM大师的Oracle 9i&10g编程艺术)

            scott@ASMDB> create table tb_test(col int);     --创建表tb_test

 

            scott@ASMDB> create or replace procedure proc1  --创建存储过程proc1使用绑定变量来插入新记录

              2  as

              3  begin

              4      for i in 1..10000

              5      loop

              6          execute immediate 'insert into tb_test values(:n)' using i;

              7      end loop;

              8  end;

              9  /

 

            Procedure created.

 

            scott@ASMDB> create or replace procedure proc2 --创建存储过程proc2,未使用绑定变量,因此每一个SQL插入语句都会硬解析

              2  as

              3  begin

              4      for i in 1..10000

              5      loop

              6          execute immediate 'insert into tb_test values('||i||')';

              7      end loop;

              8  end;

              9  /

 

            Procedure created.

 

            scott@ASMDB> exec runstats_pkg.rs_start

 

            PL/SQL procedure successfully completed.

 

            scott@ASMDB> exec proc1;

 

            PL/SQL procedure successfully completed.

 

            scott@ASMDB> exec runstats_pkg.rs_middle;

 

            PL/SQL procedure successfully completed.

 

            scott@ASMDB> exec proc2;

 

            PL/SQL procedure successfully completed.

 

            scott@ASMDB> exec runstats_pkg.rs_stop(1000);

            Run1 ran in 1769 hsecs

            Run2 ran in 12243 hsecs             --run2运行的时间是run1/1769≈

            run 1 ran in 14.45% of the time  

 

            Name                                Run1      Run2      Diff

            LATCH.SQL memory manager worka       410     2,694     2,284

            LATCH.session allocation             532     8,912     8,380

            LATCH.simulator lru latch             33     9,371     9,338

            LATCH.simulator hash latch            51     9,398     9,347

            STAT...enqueue requests               31    10,030     9,999

            STAT...enqueue releases               29    10,030    10,001

            STAT...parse count (hard)              4    10,011    10,007    --硬解析的次数,前者只有四次

            STAT...calls to get snapshot s        55    10,087    10,032

            STAT...parse count (total)            33    10,067    10,034

            STAT...consistent gets               247    10,353    10,106

            STAT...consistent gets from ca       247    10,353    10,106

            STAT...recursive calls            10,474    20,885    10,411

            STAT...db block gets from cach    10,408    30,371    19,963

            STAT...db block gets              10,408    30,371    19,963

            LATCH.enqueues                       322    21,820    21,498    --闩的队列数比较

            LATCH.enqueue hash chains            351    21,904    21,553

            STAT...session logical reads      10,655    40,724    30,069

            LATCH.library cache pin           40,348    72,410    32,062    --库缓存pin

            LATCH.kks stats                        8    40,061    40,053

            LATCH.library cache lock             318    61,294    60,976

            LATCH.cache buffers chains        51,851   118,340    66,489

            LATCH.row cache objects              351   123,512   123,161

            LATCH.library cache               40,710   234,653   193,943

            LATCH.shared pool                 20,357   243,376   223,019

 

            Run1 latches total versus runs -- difference and pct

            Run1      Run2      Diff     Pct

            157,159   974,086   816,927  16.13%          --proc2使用闩的数量也远远多于proc1,其比值是.13% 

 

            PL/SQL procedure successfully completed.

           

        由上面的示例可知,在未使用绑定变量的情形下,不论是解析次数,闩使用的数量,队列,分配的内存,库缓存,行缓存远远高于绑定

        变量的情况。因此尽可能的使用绑定变量避免硬解析产生所需的额外的系统资源。

       

        绑定变量的优点

            减少SQL语句的硬解析,从而减少因硬解析产生的额外开销(CPU,Shared pool,latch)。其次提高编程效率,减少数据库的访问次数。

        绑定变量的缺点

            优化器就会忽略直方图的信息,在生成执行计划的时候可能不够优化。SQL优化相对比较困难

 

六、总结

    1.尽可能的避免硬解析,因为硬解析需要更多的CPU资源,闩等。

    2.cursor_sharing参数应权衡利弊,需要考虑使用similarforce带来的影响。

    3.尽可能的使用绑定变量来避免硬解析。

   

七、更多参考

有关闪回特性请参考

        Oracle 闪回特性(FLASHBACK DATABASE)

Oracle 闪回特性(FLASHBACK DROP & RECYCLEBIN)

Oracle 闪回特性(Flashback Query、Flashback Table)

Oracle 闪回特性(Flashback Version、Flashback Transaction)

 

有关基于用户管理的备份和备份恢复的概念请参考:

        Oracle 冷备份

        Oracle 热备份

        Oracle 备份恢复概念

        Oracle 实例恢复

        Oracle 基于用户管理恢复的处理(详细描述了介质恢复及其处理)

       

    有关RMAN的恢复与管理请参考:

        RMAN 概述及其体系结构

        RMAN 配置、监控与管理

        RMAN 备份详解

        RMAN 还原与恢复

       

    有关Oracle体系结构请参考:

        Oracle 实例和Oracle数据库(Oracle体系结构)

        Oracle 表空间与数据文件

        Oracle 密码文件

        Oracle 参数文件

Oracle 数据库实例启动关闭过程

        Oracle 联机重做日志文件(ONLINE LOG FILE)

        Oracle 控制文件(CONTROLFILE)

        Oracle 归档日志

   

目录
相关文章
|
SQL Oracle 关系型数据库
问题出在Debezium Oracle Connector的日志解析器上
问题出在Debezium Oracle Connector的日志解析器上
146 2
|
2月前
|
负载均衡 Oracle 网络协议
Oracle中TAF与SCANIP全面解析
通过本文的解析,读者可以清晰地理解Oracle中TAF与SCAN IP的概念、工作原理及其在实际应用中的优势和局限性。TAF通过自动故障转移提升了会话的高可用性,而SCAN则通过简化客户端连接和负载均衡提升了集群的可管理性和扩展性。这两种技术在现代企业数据库架构中扮演着重要角色,能够显著提高系统的稳定性和可用性。
147 6
|
5月前
|
监控 Oracle 关系型数据库
"深度剖析:Oracle SGA大小调整策略——从组件解析到动态优化,打造高效数据库性能"
【8月更文挑战第9天】在Oracle数据库性能优化中,系统全局区(SGA)的大小调整至关重要。SGA作为一组共享内存区域,直接影响数据库处理能力和响应速度。本文通过问答形式介绍SGA调整策略:包括SGA的组成(如数据缓冲区、共享池等),如何根据负载与物理内存确定初始大小,手动调整SGA的方法(如使用`ALTER SYSTEM`命令),以及利用自动内存管理(AMM)特性实现智能调整。调整过程中需注意监控与测试,确保稳定性和性能。
463 2
|
7月前
|
SQL DataWorks Oracle
DataWorks产品使用合集之datax解析oracle增量log日志该如何操作
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
75 0
|
8月前
|
缓存 Oracle 关系型数据库
oracle 软软解析
oracle 软软解析
48 0
|
Oracle 关系型数据库
行列转换利器:Oracle pivot函数全面解析
行列转换利器:Oracle pivot函数全面解析
167 0
行列转换利器:Oracle pivot函数全面解析
|
SQL Oracle 关系型数据库
SQL解析...没有什么大不了的?#oracle(译文)
在Oracle中编写SQL语句时,我们都强调使用共享SQL的重要性,换种说法是:在适当的情况下使用绑定变量,我们大多数人可能都已经看过关于这个原则的标准演示。经典的演示是比较两个类似的脚本,其中一个使用生成大量包含字面量的 SQL 语句,另一个使用绑定变量重新重写相同的脚本以获得显著的改进
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
113 2
|
29天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
|
29天前
|
设计模式 存储 安全
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析
结构型模式描述如何将类或对象按某种布局组成更大的结构。它分为类结构型模式和对象结构型模式,前者采用继承机制来组织接口和类,后者釆用组合或聚合来组合对象。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象结构型模式比类结构型模式具有更大的灵活性。 结构型模式分为以下 7 种: • 代理模式 • 适配器模式 • 装饰者模式 • 桥接模式 • 外观模式 • 组合模式 • 享元模式
【23种设计模式·全精解析 | 创建型模式篇】5种创建型模式的结构概述、实现、优缺点、扩展、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多