关于ORACLE的硬解析和软解析与MySQL的查询缓存query_cache探讨

今天在项目中探讨到Oracle对于SQL语句的解析方法以及MySQL相应的处理方法:

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

先来看一下Oracle的机制:

oralce中有硬解析和软解析的概念,为了能够理解好这两个概念,我们先引入oralce是怎么执行SQL的

 

oracle在执行SQL的时候有如下步骤:

1 语法检查,例如SQL的拼写

2 语义检查,例如sql中的对象是否存在及相关的权限

3 sql解析,对sql进行语法解析,生成解析树及执行计划

  3.1 硬解析 包括语法和语义分析,查看共享池是否有解析好的结果,然后选择执行计划和生成执行计划,执行sql

  3.2 软解析,如果在共享池中有解析好的结果,直接执行sql

创建解析树、生成执行计划对于sql的执行来说是开销昂贵的动作,所以,应当极力避免硬解析,尽量使用软解析。这就是在很多项目中,倡导开发设计人员对功能相同的代码要努力保持代码的一致性,以及要在程序中多使用绑定变量的原因。

  3.3 其中查看共享池的部分涉及到利用sql的哈希值和共享池中的哈希值做比较,这些比较包括大小写,字符串一致性,空格,注释

4 执行sql

这里再插入一个绑定变量的概念

绑定变量简单点理解就是在sql语句中的参数的地方使用一个占位符

 

1select * from emp where empno=7788    --未使用绑定变量
2select * from emp where empono=:eno   --:eno即为绑定变量

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

另外,有一点要注意一下,DDL每次都是硬解析,dml会走软解析

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

MySQL没有全局sql字节码缓存,所有的语句都要解析成语法树,所以mysql不存在软硬解析的机制,

相对应的mysql的处理机制在下面最了详细的分析:. 

 

1:先看MySQL整体模块图: 

 
(图片取自MySQL核心技术) 
从图中可以看出MySQL的模块职责分工明确,不愧是Monty团队20年的结晶.好产品是靠持续的汗水浇灌的啊(扯远了)。。。 
其中MySQL语句大概分两种:SQL和命令 

SQL无非就是DDL,DML,命令是mysql自身语法如:show [table,process,database,index] , source ...等等. 

用一条DML为例,连接管理器模块,线程模块,权限模块职责很明确此处略. 

第一步由Commander Dispatcher(命令)模块统一接受处理, 
1)如果开启全查询日志(是log 不是slow-low),会记录所有的语句(包括错误语句) 
2)如果开启查询缓存(query_cache_type=1)会先判断语句是否可缓存,如果可以使用语句和客户端信息等的hash值查询query cache模块 如果找到数据短路. 

第二步将语句转交parser模块进行解析,并发送给不同模块(优化器,表修改模块,表维护模块,复制模块,状态模块等) 
其中最重要的是优化器模块,这个是所有数据库的核心,所有的DML都经过它完成 
(这个后面的文章做进一步总结和学习,sql的快与慢全靠他.) 

第三步假如进入优化器模块:MySQL的优化器的只定义了抽象存储引擎(Handler) 
具体实现由存储引擎完成(mysql的插件引擎特性) 

第四步进入存储引擎内部完成具体的数据读取和修改,内部有很复杂的处理流程和日志体系(如:innodb buffer_pool,redo,undb等..). 

第五步返回数据,如果开启查询缓存会做尝试做缓存.最后完成清理工作,回收线程. 
这里非常粗粒度的介绍的MySQL模块见的相互配合完成sql的过程,具体流程比这复杂的多,正在看书并结合源码研究中。。 
简单语句流程到这里,MySQL下面看看另一张关注parser, optimizer的流程图 
 
(图片取自高性能MySQL) 

这张图更能体现sql的一些解析处理和优化过程. 
这里有个问题需要介绍以下MySQL没有全局sql字节码缓存,所有的语句都要解析成语法树. 
如果使用PrepareStatement的机制发送SQL 则mysql只在当前session支持预编译 
官方解释如下: 
http://dev.mysql.com/doc/refman/5.1/en/sql-syntax-prepared-statements.html 
这里和Oracle由很大不同,也就是说你没有使用变量绑定,MySQL也不会像Oracle那样迅速被拖慢... 
mysql有SQL服务器模式,通过sql-mode参数体现. 
可以随时更改自己的会话 sql_mode值 
主要sql_mode取值如下: 
· ANSI: 
· STRICT_TRANS_TABLES: 
·TRADITIONAL 
·ALLOW_INVALID_DATES 
·ANSI_QUOTES 
·ERROR_FOR_DIVISION_BY_ZERO 
·HIGH_NOT_PRECEDENCE 
查看官方文档解释:http://dev.mysql.com/doc/refman/5.1/zh/database-administration.html#server-sql-mode 
你在mysql中遇到不一致的sql执行结果时,记得看看你session的sql_mode 

 

 

 

转载于:https://www.cnblogs.com/simplelogic/p/3252975.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle 中的 SQL 解析分为解析解析两种方式。解析是指将 SQL 语句转换为可执行的代码并进行编译,而解析是指通过查询缓存中已有的 SQL 语句执行计划来执行查询操作,从而避免对 SQL 语句进行编译。解析虽然可以提高查询效率,但是如果解析的频率过高,就会导致性能下降和服务器资源浪费。以下是一些编码解析的改进方法: 1. 尽量避免使用动态 SQL:动态 SQL 语句需要在运行时进行解析和编译,会导致解析次数增加。如果可以使用静态 SQL 语句,就应该尽量避免使用动态 SQL。 2. 使用参数化查询:参数化查询可以将 SQL 语句中的变量替换为占位符,避免生成大量的 SQL 语句,从而减少解析次数。 3. 统一 SQL 语句格式:统一 SQL 语句格式可以避免生成不同的 SQL 语句,从而减少解析次数。 4. 使用绑定变量:绑定变量可以避免在每次执行 SQL 语句时都重新解析和编译 SQL 语句,从而减少解析次数。 5. 使用 SQL 语句缓存:使用 SQL 语句缓存可以避免对相同的 SQL 语句进行重复解析和编译,从而减少解析次数。 6. 增加共享池大小:共享池是存储 SQL 语句和执行计划的缓存区域,如果共享池空间不足,就会导致频繁的解析和编译。可以通过增加共享池大小来减少解析次数。 总之,在编写 SQL 语句的过程中,需要尽量避免使用动态 SQL 语句,使用参数化查询和绑定变量等方法来减少解析次数,从而提高查询性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值