这篇文章是参考甲骨论老相老师所做的教学视频:
http://v.youku.com/v_show/id_XMzkyMTczMTQ4.html
所做的学习笔记:

接上文:
http://nvd11.blog.163.com/blog/static/200018312201301875752730/
sql 是在shared Pool里面解析成执行计划的.

如图:


        1.什么是SQL语句共享

        sql 语句传入shared pool后, 会被先转换成ASCII码, 然后经过一系列运算,其中包括HASH运算,得出HASH值,然后得出一串数字,并包含1个内存链chain号码.

Server Process 就会拿着chain号码和HASH号码,到Library cache上找到对应的内存链chain, 然后遍历上面的chunk(比较Hash值), 如果有1个chunk的Hash与之相同,则证明这条sql曾经被硬解析过, 就直接可以拿出对应执行计划, 这就是软解析.

我们也可以说这条sql与之前硬解析过的sql共享了.

如果找不到hash值相同的chunk,  则认为这条sql未被硬解析过, 就要执行上图的动作2,进行硬解析.

所以可以看出,那个HASH值十分重要, 而hash值是由ASCII码运算出来的, 所以共享sql之间的ASCII码要相同.

而ASCII是由SQL语句的字符决定的.  所以两条共享sql语句的每个字符要相同. 而且大小写都要相同

举个例子: 下面3条语句
        select /*comment_1*/ count(1) from dba_tables where table_name = 'EMP';
        select /*comment_1*/ count(1) from dba_tables where table_name = 'DEPT';
        select /*comment_1*/ count(1) from  dba_tables where table_name = 'DEPT';

首先,很明显 第一条语句和第二条语句不相同, 因为EMP 和 DEPT 是两个不同的字符
       第二条和第三条呢?  也不相同, 因为第二条 from 与 dba_tables直接只有1个空格, 而第3条有2个! 所以他们的ASCII码不同,所以规范编写SQL语句很重要啊.

 ===============================================分割线===============================
2.判断SQL语句有无共享

下面我分别执行上面3条语句1次

注意第2条和第3条语句的空格区别哦

然后可以去v$sql 去查看已执行过的sql语句:
 select sql_id,sql_text,executions from v$sql where sql_text like '%comment_1%';

可以看出这3条sql语句分别被执行了1次    (因为调整显示格式, 查询v$sql的这条执行3次)
也就说进行了3次硬解析.

其实每执行1条sql语句, 都会分配1个sql_id(参见上图),上面3条语句被分配3个sql_id, 所以oracle认为上面3条语句是不一样的.

所以Oracle中sql语句要相同:
则所有字符要一样, 包括空格,空行,回车...

例如, 如果要第3条语句与第一条语句共享, 则要去掉from 和 dba_tables之间的1个空格:
我们在执行一次:

可发现,v$sql中并没有多出一个sql_id, 只不过第一条的执行次数变成了2,  也就是说第4次执行的那条跟第一条的sql_id是一样的,因为它们的字符完全一样.

那么第一条和第二条sql能不能共享呢, 因为条件'EMP' 跟 'DEPT' 完全不同啊, 貌似是个硬伤.

方法是有的:
就是用1个相同名字的变量, 分别赋值'EMP'和'DEPT'各执行一次, 因为变量名相同.
做个例子:

写1个 sql 脚本如下:

上面的脚本会插入11行数据进入表test, 虽然每一行的值都是不同, 但是我们可以用变量  i来装载它.
然后使用 execute 来执行sql语句.

下面执行这个脚本:

在查看v$sql 视图:

可以见到11次sql语句之分配了1个 sql_id , 用:1 来取代实际的值. 也就是说11条insert语句之产生1此硬解析, 其余10次是软解析,成功共享SQL.
这个方法很重要, 可以想象一下银行业务, 可能经常大量地使用同一条sql语句,但是参数次次都不同, 如果在写程序时不使用绑定变量,则会产生大量的硬解析,  而使用了绑定变量去取代参数, 就能避免这个情况!

所以总结一下共享SQL的关键:

1. 严格统一书写风格
2. 使用绑定变量

提醒下, v$sql实在上就是缓存在shared pool里的sql语句信息.
可以用alter system flush shared pool 来清空v$sql, 不过接下来就大量硬解 你懂的.

 ===============================================分割线===============================

3.如何找出未被共享(硬解析)的sql语句:

原理都好简单, 因为如果一条sql未被共享,则这条sql在v$sql里的执行次数为1.
所以只需查找v$sql
select sql_id, sql_fulltext,executions from v$sql where sql_text like '%from t%' and executions = 1 order by sql_text ;

注意绿色高亮部分根据实际情况修改

order by 排序很重要啊, 因为有些sql的确只被用户执行了一次, 用order by就可找出那些类似的sql,而被硬解析多次了~

下面做个例子,
修改一下上面的脚本, 令到循环中每次执行的语句都不一样(参数不一样)
如下图, 注意右边是修改后的:
执行了900几次..

然后执行这个修改后的脚本:

接下来用
select sql_id, sql_fulltext,executions from v$sql where sql_text like '%insert%' and executions = 1 order by sql_text;
查看 未被共享的语句.

接下来去查看导出来的log文件, 通常就可以分析出哪些sql语句未被共享而被执行大量硬解析了..

这是1个很经典的查找未被共享sql语句的方法, 用于数据库优化.

===============================================分割线===============================

4. 设置cursor_sharing参数
找到未被共享的sql语句后怎么做呢, 一般会交给程序员,让他们修改.

但是做过码农的都知道, 程序里的代码有些时候不是那么好改了,有时真的牵一发而动全身啊..

那改不了怎么办.

其实还有1个办法是设置oracle的一个参数: cursor_sharing
我们先查看当前默认的参数值是什么:

可以见到当前值是EXACT, 代表什么意思呢, 我们去oracle官方文档查下:

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.

  • EXACT

    Only allows statements with identical text to share the same cursor.

可以见到, 游标共享参数决定了什么情况下可以共享SQL

EXACT : 只有当sql语句完全一样才共享sql

关键是FORCE了:

首先共享SQL失败原因有两种:

1.是书写不规范(大小写, 空格)

2. 没有用绑定变量去取代参数.

对于第一种原因的sql共享失败, 这个cursor_sharing设置也没办法解决, 不过很容易交给程序员解决.

而将cursor_sharing设置为force 可以解决第2种情况,

我们测试一下:

首先将cursor_sharing 设置为force

跟住清空shared pool缓存:

然后我们再执行一次上面执行过的那个脚本:

执行:

我们再去查看v$sql..
但是由这个测试来讲是无效果的... 而老相在视频里没提供测试..
可以见到 sql语句并没有共享, 依然是没一条insert 语句分配1个sql id.

于是我私人再做多个测试,睇下这个参数会不会影响硬解析的数量.

首先将cursor_sharing设置成默认的'EXACT', 并清空shared pool缓存.

接着查看当前硬解析和软解析数量:

可以记下:
当前已经发生过的解析数量总数为: 611230
其中硬解析数量为: 35774

这时我们执行一次insert脚本:

再次查看解析数量:

其中解析数量总数增加了  613301 - 611230 =  2071
而硬解析数量增加了 36778 - 35774 =  1004
可以看出硬解析的数量是相当接近 脚本中循环执行的insert 语句数量的!

这是我们将cursor_sharing 设置为Force
并且清空shared pool

再查看当前的解析数量:

当前已经发生过的解析数量总数为: 616473
其中硬解析数量为: 37432

这时我们再次执行一次insert脚本:

再次查看解析数量:

其中解析数量总数增加了  618008 - 616473 =  1535
而硬解析数量增加了 38511 - 37432 =  1079

尼玛硬解析数量反而增加了

我觉得原因是可能这个参数对我脚步那种sql 无作用, 至于到底会影响哪些sql共享, 以后再研究了...


共享SQL语句减少硬解析相关推荐

  1. mysql 硬解析 软解析_ORACLE sql语句的硬解析与软解析(收藏)

    我们都知道在Oracle中每条SQL语句在执行之前都需要经过解析,这里面又分为软解析和硬解析.那么这两种解析有何不同之处呢?它们又分别是如何进行解析呢?Oracle内部解析的步骤又是如何进行的呢?下面 ...

  2. android连接ecs sql server_MySQL 执行 SQL 语句的过程解析

    前言 作为一名菜鸟程序员,我已经工作两年了.从事后端开发工作. 后端开发中,MySQL 可以说是必会的一门技能了.刚开始时我以为数据库就是写写 SQL 语句,做做增删改查业务.直到我写的程序多次导致 ...

  3. sql like 绑定变量_码硬解析的改进方法之二使用绑定变量

    绑定变量要求变量名称,数据类型以及长度是一致,否则无法使用软解析 绑定变量(bind variable)是指在DML语句中使用一个占位符,即使用冒号后面紧跟变量名的形式,如下 select * fro ...

  4. PLSQL_解析过程及硬解析和软解析的区别(案例)

    2014-08-11 Created By BaoXinjian 一.摘要 Oracle硬解析和软解析是我们经常遇到的问题,所以需要考虑何时产生软解析何时产生硬解析,如何判断 1. SQL的执行过程 ...

  5. 面试题: !=!=未看12 略多 sql语句练习 非常 有用

    JAVA面试总结 2015年03月25日 16:53:40 阅读数:4306 刚才看到的,先转载过来,没准以后用到-- 面试总结 2013年8月6日: 问题2:Hibernate的核心接口有哪些?   ...

  6. sql java 解析_Java 实现对Sql语句解析

    最近要实现一个简易的数据库系统,除了要考虑如何高效的存储和访问数据,建立表关系外,对基本的sql查询语句要做一个解析,这样我们才能知道用户的查询要求:因为时间关系,参考了已有的一篇文章,并对其实现中出 ...

  7. java sql语句逗号_Java 实现对Sql语句解析

    最近要实现一个简易的数据库系统,除了要考虑如何高效的存储和访问数据,建立表关系外,对基本的sql查询语句要做一个解析,这样我们才能知道用户的查询要求:因为时间关系,参考了已有的一篇文章,并对其实现中出 ...

  8. 基于简单sql语句的sql解析原理及在大数据中的应用

    基于简单sql语句的sql解析原理及在大数据中的应用 李万鸿 老百姓呼吁打土豪分田地.共同富裕,总有一天会实现. 全面了解你所不知道的外星人和宇宙真想:http://pan.baidu.com/s/1 ...

  9. Oracle SQL语句执行步骤

    Oracle中SQL语句执行过程中,Oracle内部解析原理如下: 1.当一用户第一次提交一个SQL表达式时,Oracle会将这SQL进行Hard parse,这过程有点像程序编译,检查语法.表名.字 ...

最新文章

  1. nodejs获取ASP.Net WebAPI(IIS Windows验证)
  2. 【Java小工匠聊密码学】-密码学--综述
  3. 某阿里程序员求助:绩效背1,老板让他主动走!敢要n+1就在背调时说坏话!怎么办?网友:大不了鱼死网破!...
  4. Jquery获取外网IP
  5. Java程序员从笨鸟到菜鸟之(八十六)跟我学jquery(二)大话jquery选择器
  6. textContent、innerHTML、innerText、outerText、outerHTML、nodeValue使用场景和区别
  7. hide subscribers is a good approach if you have a very limited subscribers
  8. Git Bash关键命令
  9. 四部门联合发文推动数学科学发展,释放支持高校建设基础数学中心信号!
  10. recipe for target 'aclocal.m4' failed
  11. 【hdu6588】2019多校第一场K题function,反演
  12. web开发快餐式入门指南 0. 写在前面
  13. [递推][jzyzojP1252]:递推专练4
  14. 一文带你完全掌握机器人DH参数建模(详细步骤+实例+代码)
  15. xmind下载安装电脑版教程
  16. APP内测分发平台源码|应用分发源码|开源分发平台搭建
  17. 快速阶乘算法python_python实现N阶乘的算法
  18. 官方精简版Windows10:微软自己都看不过去了
  19. python 小工具 之 房贷计算器
  20. 使用API函数 GetACP 获取Windows系统当前代码页(字符编码)

热门文章

  1. [HOW TO]-官网拉取Trusty-TEE的代码
  2. TEE Internal core API介绍(globalplatform)
  3. NetGear 夜鹰 RAX40V2 设备与固件分析
  4. 检测IAT HOOK思路
  5. python获取android手机信息
  6. PE学习(十一)第十一章:动态加载技术
  7. 1.10 Iterator(迭代器)遍历集合元素
  8. Codeforces Round #753 (Div. 3) A-E
  9. 2.1.5 编码与调制(1)
  10. JVM堆新生代分配比例