怎样判断一个SQL语句是硬解析还是软解析?Sql语句解析过程

2024-07-16 12:40:06 :13

怎样判断一个SQL语句是硬解析还是软解析?Sql语句解析过程

这篇文章给大家聊聊关于sql解析,以及怎样判断一个SQL语句是硬解析还是软解析对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。

本文目录

怎样判断一个SQL语句是硬解析还是软解析

只要执行的sql语句文本相同,并且对应sql的执行计划已经缓存在oracle的内存(library cache)中,那么无论你怎么去执行这条sql,都不会硬解析,而是软解析。相反来说,如果这个sql你第一次执行,或者之前执行sql的执行计划已经从oracle内存中置换出来,那么肯定会硬解析。建议看一下oracle内存方面的资料,会有相对应的解释。

Sql语句解析过程

  为了将用户写的SQL文本转化为Oracle认识的且可执行的语句 这个过程就叫做解析过程 解析分为硬解析和软解析 一条SQL语句在第一次被执行时必须进行硬解析

  当客户端发出一条SQL语句(也可以是一个存储过程或者一个匿名PL/SQL块)进入shared pool时(注意 我们从前面已经知道 Oracle对这些SQL不叫做SQL语句 而是称为游标 因为Oracle在处理SQL时 需要很多相关的辅助信息 这些辅助信息与SQL语句一起组成了游标) Oracle首先将SQL文本转化为ASCII值 然后根据hash函数计算其对应的hash值(hash_value) 根据计算出的hash值到library cache中找到对应的bucket 然后比较bucket里是否存在该SQL语句

  如果不存在 则需要按照我们前面所描述的 获得shared pool latch 然后在shared pool中的可用chunk链表(也就是bucket)上找到一个可用的chunk 之后释放shared pool latch 在获得了chunk以后 这块chunk就可以认为是进入了library cache 接下来 进行硬解析过程 硬解析包括以下几个步骤

  对SQL语句进行文法检查 看是否有文法错误 比如没有写from select拼写错误等 如果存在文法错误 则退出解析过程

  到数据字典里校验SQL语句涉及的对象和列是否都存在 如果不存在 则退出解析过程 这个过程会加载dictionary cache

  将对象进行名称转换 比如将同名词翻译成实际的对象等 比如select * from t中 t是一个同名词 指向hr t 于是Oracle将t转换为hr t 如果转换失败 则退出解析过程

  检查发出SQL语句的用户是否具有访问SQL语句里所引用的对象的权限 如果没有权限 则退出解析过程

  通过优化器创建一个最优的执行计划 这个过程会根据数据字典里记录的对象的统计信息 来计算最优的执行计划 这一步牵涉大量数学运算 是最消耗CPU资源的

  将该游标所产生的执行计划 SQL文本等装载进library cache的heap中

  在硬解析的过程中 进程会一直持有library cache latch 直到硬解析结束为止 硬解析结束以后 会为SQL语句产生两个游标 一个是父游标 另一个是子游标 父游标里主要包含两种信息 SQL文本以及优化目标(optimizer goal) 父游标在第一次打开时被锁定 直到其他所有的session都关闭该游标后才被解锁 当父游标被锁定的时候是不能被交换出library cache的 只有在解锁以后才能被交换出library cache 父游标被交换出内存时 父游标对应的所有子游标也被交换出library cache 子游标包括游标所有的信息 比如具体的执行计划 绑定变量等 子游标随时可以被交换出library cache 当子游标被交换出library cache时 Oracle可以利用父游标的信息重新构建出一个子游标来 这个过程叫reload 可以使用下面的方式来确定reload的比率

  select *sum(reloads)/sum(pins) Reload_Ratio from v$librarycache;

  一个父游标可以对应多个子游标 子游标具体的个数可以从视图v$sqlarea的version_count字段体现出来 而每个具体的子游标则全都在视图v$sql里体现 当具体绑定变量的值与上次绑定变量的值有较大差异(比如上次执行的绑定变量值的长度是 位 而这次执行绑定变量的值的长度是 位)时或者当SQL语句完全相同 但是所引用的表属于不同的用户时 都会创建一个新的子游标

  如果在bucket中找到了该SQL语句 则说明该SQL语句以前运行过 于是进行软解析 软解析是相对于硬解析而言的 如果解析过程中 可以从硬解析的步骤中去掉一个或多个的话 这样的解析就是软解析 软解析分为以下三种类型

  第一种是某个session发出的SQL语句与library? cache里其他session发出的SQL语句一致 这时 该解析过程中可以去掉硬解析中的 和 但是仍然要进行硬解析过程中的 也就是表名和列名检查 名称转换和权限检查

  * 第二种是某个session发出的SQL语句是该session之前发出的曾经执行过的SQL语句 这时 该解析过程中可以去掉硬解析中的 和 这四步 但是仍然要进行权限检查 因为可能通过grant改变了该session用户的权限

  * 第三种是当设置了初始化参数session_cached_cursors时 当某个session第三次执行相同的SQL时 则会把该SQL语句的游标信息转移到该session的PGA里 这样 该session以后再执行相同的SQL语句时 会直接从PGA里取出执行计划 从而跳过硬解析的所有步骤 这种情况下 是最高效的解析方式 但是会消耗很大的内存

  我们举一个例子来说明解析SQL语句的过程 在该测试中 绑定变量名称相同 但是变量类型不同时 所出现的解析情况 如下所示

  首先 执行下面的命令 清空shared pool里所有的SQL语句

  SQL》 alter system flush shared_pool;

  然后 定义一个数值型绑定变量 并为该绑定变数赋一个数值型的值以后 执行具体的查询语句

  SQL》 variable v_obj_id number;

  SQL》 exec :v_obj_id := ;

  SQL》 select object_id object_name from sharedpool_test

  where object_id=:v_obj_id;

  OBJECT_ID       OBJECT_NAME

       

              AGGXMLIMP

  接下来 定义一个字符型的绑定变量 变量名与前面相同 为该绑定变数赋一个字符型的值以后 执行相同的查询

  SQL》 variable v_obj_id varchar ( );

  SQL》 exec :v_obj_id := ;

  SQL》 select object_id object_name from sharedpool_test

  where object_id=:v_obj_id;

  OBJECT_ID       OBJECT_NAME

       

              AGGXMLIMP

  然后我们到视图v$sqlarea里找到该SQL的父游标的信息 并到视图v$sql里找该SQL的所有子游标的信息

  SQL》 select sql_text version_count from v$sqlarea where

  sql_text like %sharedpool_test% ;

  SQL_TEXT

  VERSION_COUNT

  

  

  select object_id object_name from sharedpool_test where

  object_id=:v_obj_id         

  SQL》 select sql_text child_address address from v$sql

  where sql_text like %sharedpool_test% ;

  SQL_TEXT

  CHILD_ADDRESS  ADDRESS

  

  

  select object_id object_name from sharedpool_test where

  object_id=:v_obj_id    F

   B D

  select object_id object_name from sharedpool_test where

  object_id=:v_obj_id    FC

   B D

  从记录父游标的视图v$sqlarea的version_count列可以看到 该SQL语句有 个子游标 而从记录子游标的视图v$sql里可以看到 该SQL文本确实有两条记录 而且它们的SQL文本所处的地址(ADDRESS列)也是一样的 但是子地址(CHILD_ADDRESS)却不一样 这里的子地址实际就是子游标所对应的heap 的句柄

lishixinzhi/Article/program/Oracle/201311/18653

C# 解析 sql语句

select 字段 from 表 where 条件//这就是基本的查询语句,根据where条件,从指定表中,查询出指定的字段值的集合,比如select userName from user where ID=1,就是从user表中找出ID是1的用户名字获取字段集合如:select a.Song_Name,B.Art_Name,a.Create_date from Songset a left join on artset b on a.art_code=b.artcode//这个是一个连表查询,关键词是left join,你可以去查下它的相关信息。//把Songet视为a表,把artset视为b表,select出a表的Song Name、b表的Art_Name、a表的Create_date,条件是a表的artcode=b表的artcode

oracle sql是怎么解析的

导读:Oracle的后台运作原理是什么?我们的一条命令是如何被执行的?今天我们就从一条简单的Select语句开始,看看Oracle数据库后台的运作机制。Select语句可以说是DBA和数据库开发者在工作中使用最多的语句之一,但这条语句是如何执行?在Oracle数据库中又是如何运作的呢?今天我们就从一条简单的Select语句开始,看看Oracle数据库后台的运作机制。这对于我们之后的系统管理与故障排除非常有帮助。第一步:客户端把语句发给服务器端执行当我们在客户端执行select语句时,客户端会把这条SQL语句发送给服务器端,让服务器端的进程来处理这语句。也就是说,Oracle客户端是不会做任何的操作,他的主要任务就是把客户端产生的一些SQL语句发送给服务器端。虽然在客户端也有一个数据库进程,但是,这个进程的作用跟服务器上的进程作用事不相同的。服务器上的数据库进程才会对SQL语句进行相关的处理。不过,有个问题需要说明,就是客户端的进程跟服务器的进程是一一对应的。也就是说,在客户端连接上服务器后,在客户端与服务器端都会形成一个进程,客户端上的我们叫做客户端进程;而服务器上的我们叫做服务器进程。所以,由于所有的SQL语句都是服务器进程执行的,所以,有些人把服务器进程形象地比喻成客户端进程的“影子”。第二步:语句解析当客户端把SQL语句传送到服务器后,服务器进程会对该语句进行解析。同理,这个解析的工作,也是在服务器端所进行的。虽然这只是一个解析的动作,但是,其会做很多“小动作”。1. 查询高速缓存。服务器进程在接到客户端传送过来的SQL语句时,不会直接去数据库查询。而是会先在数据库的高速缓存中去查找,是否存在相同语句的执行计划。如果在数据高速缓存中,刚好有其他人使用这个查询语句的话,则服务器进程就会直接执行这个SQL语句,省去后续的工作。所以,采用高速数据缓存的话,可以提高SQL语句的查询效率。一方面是从内存中读取数据要比从硬盘中的数据文件中读取数据效率要高,另一方面,也是因为这个语句解析的原因。不过这里要注意一点,这个数据缓存跟有些客户端软件的数据缓存是两码事。有些客户端软件为了提高查询效率,会在应用软件的客户端设置数据缓存。由于这些数据缓存的存在,可以提高客户端应用软件的查询效率。但是,若其他人在服务器进行了相关的修改,由于应用软件数据缓存的存在,导致修改的数据不能及时反映到客户端上。从这也可以看出,应用软件的数据缓存跟数据库服务器的高速数据缓存不是一码事。2. 语句合法性检查。当在高速缓存中找不到对应的SQL语句时,则数据库服务器进程就会开始检查这条语句的合法性。这里主要是对SQL语句的语法进行检查,看看其是否合乎语法规则。如果服务器进程认为这条SQL语句不符合语法规则的时候,就会把这个错误信息,反馈给客户端。在这个语法检查的过程中,不会对SQL语句中所包含的表名、列名等等进行SQL他只是语法上的检查。3. 语言含义检查。若SQL语句符合语法上的定义的话,则服务器进程接下去会对语句中的字段、表等内容进行检查。看看这些字段、表是否在数据库中。如果表名与列名不准确的话,则数据库会就会反馈错误信息给客户端。所以,有时候我们写select语句的时候,若语法与表名或者列名同时写错的话,则系统是先提示说语法错误,等到语法完全正确后,再提示说列名或表名错误。若能够掌握这个顺序的话,则在应用程序排错的时候,可以节省时间。4. 获得对象解析锁。当语法、语义都正确后,系统就会对我们需要查询的对象加锁。这主要是为了保障数据的一致性,防止我们在查询的过程中,其他用户对这个对象的结构发生改变。对于加锁的原理与方法,我在其他文章中已经有专门叙述,在这里就略过不谈了。5. 数据访问权限的核对。当语法、语义通过检查之后,客户端还不一定能够取得数据。服务器进程还会检查,你所连接的用户是否有这个数据访问的权限。若你连接上服务器的用户不具有数据访问权限的话,则客户端就不能够取得这些数据。故,有时候我们查询数据的时候,辛辛苦苦地把SQL语句写好、编译通过,但是,最后系统返回个 “没有权限访问数据”的错误信息,让我们气半死。这在前端应用软件开发调试的过程中,可能会碰到。所以,要注意这个问题,数据库服务器进程先检查语法与语义,然后才会检查访问权限。6. 确定最佳执行计划。当语句与语法都没有问题,权限也匹配的话,服务器进程还是不会直接对数据库文件进行查询。服务器进程会根据一定的规则,对这条语句进行优化。不过要注意,这个优化是有限的。一般在应用软件开发的过程中,需要对数据库的sql语言进行优化,这个优化的作用要大大地大于服务器进程的自我优化。所以,一般在应用软件开发的时候,数据库的优化是少不了的。当服务器进程的优化器确定这条查询语句的最佳执行计划后,就会将这条SQL语句与执行计划保存到数据高速缓存。如此的话,等以后还有这个查询时,就会省略以上的语法、语义与权限检查的步骤,而直接执行SQL语句,提高SQL语句处理效率。第三步:语句执行语句解析只是对SQL语句的语法进行解析,以确保服务器能够知道这条语句到底表达的是什么意思。等到语句解析完成之后,数据库服务器进程才会真正的执行这条SQL语句。这个语句执行也分两种情况。一是若被选择行所在的数据块已经被读取到数据缓冲区的话,则服务器进程会直接把这个数据传递给客户端,而不是从数据库文件中去查询数据。若数据不在缓冲区中,则服务器进程将从数据库文件中查询相关数据,并把这些数据放入到数据缓冲区中。这里仍然要注意一点,就是Oracle数据库中,定义了很多种类的高速缓存。像上面所说的SQL语句缓存与现在讲的数据缓存。我们在学习数据库的时候,需要对这些缓存有一个清晰的认识,并了解各个种类缓存的作用。这对于我们后续数据库维护与数据库优化是非常有用的。第四步:提取数据当语句执行完成之后,查询到的数据还是在服务器进程中,还没有被传送到客户端的用户进程。所以,在服务器端的进程中,有一个专门负责数据提取的一段代码。他的作用就是把查询到的数据结果返回给用户端进程,从而完成整个查询动作。从这整个查询处理过程中,我们在数据库开发或者应用软件开发过程中,需要注意以下几点:一是要了解数据库缓存跟应用软件缓存是两码事情。数据库缓存只有在数据库服务器端才存在,在客户端是不存在的。只有如此,才能够保证数据库缓存中的内容跟数据库文件的内容一致。才能够根据相关的规则,防止数据脏读、错读的发生。而应用软件所涉及的数据缓存,由于跟数据库缓存不是一码事情,所以,应用软件的数据缓存虽然可以提高数据的查询效率,但是,却打破了数据一致性的要求,有时候会发生脏读、错读等情况的发生。所以,有时候,在应用软件上有专门一个功能,用来在必要的时候清除数据缓存。不过,这个数据缓存的清除,也只是清除本机上的数据缓存,或者说,只是清除这个应用程序的数据缓存,而不会清除数据库的数据缓存。二是绝大部分SQL语句都是按照这个处理过程处理的。我们DBA或者基于Oracle数据库的开发人员了解这些语句的处理过程,对于我们进行涉及到SQL语句的开发与调试,是非常有帮助的。有时候,掌握这些处理原则,可以减少我们排错的时间。特别要注意,数据库是把数据查询权限的审查放在语法语义的后面进行检查的。所以,有时会若光用数据库的权限控制原则,可能还不能满足应用软件权限控制的需要。此时,就需要应用软件的前台设置,实现权限管理的要求。而且,有时应用数据库的权限管理,也有点显得繁琐,会增加服务器处理的工作量。因此,对于记录、字段等的查询权限控制,大部分程序涉及人员喜欢在应用程序中实现,而不是在数据库上实现。

如何解析sql语句并提取出表名

先做词法分析,识别每个单词, 然后做语义分析找到表名。关键字from、into后, where前就是表名。select * from table_name where .....;insert a, b, c into table_name;delete * from table where ...;update f1 = a table where ...;

怎么用正则表达式解析sql语句

先看要解析的样例SQL语句:select * from dualSELECT * frOm dualSelect C1,c2 From tbselect c1,c2 from tbselect count(*) from t1select c1,c2,c3 from t1 where condi1=1 Select c1,c2,c3 From t1 Where condi1=1 select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3解析效果之一(isSingleLine=false):原SQL为select * from dual解析后的SQL为select * from dual原SQL为SELECT * frOm dual解析后的SQL为select * from dual原SQL为Select C1,c2 From tb解析后的SQL为select C1,c2 from tb原SQL为select c1,c2 from tb解析后的SQL为select c1,c2 from tb原SQL为select count(*) from t1解析后的SQL为select count(*) from t1原SQL为select c1,c2,c3 from t1 where condi1=1解析后的SQL为select c1,c2,c3 from t1 where condi1=1原SQL为Select c1,c2,c3 From t1 Where condi1=1解析后的SQL为select c1,c2,c3 from t1 where condi1=1原SQL为select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2解析后的SQL为select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2原SQL为Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2解析后的SQL为select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2原SQL为select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2解析后的SQL为select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2解析后的SQL为select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3解析后的SQL为select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2,g3 order by g2,g3解析效果之二(isSingleLine=true):原SQL为select * from dual解析后的SQL为select * from dual原SQL为SELECT * frOm dual解析后的SQL为select * from dual原SQL为Select C1,c2 From tb解析后的SQL为select C1, c2 from tb原SQL为select c1,c2 from tb解析后的SQL为select c1, c2 from tb原SQL为select count(*) from t1解析后的SQL为select count(*) from t1原SQL为select c1,c2,c3 from t1 where condi1=1解析后的SQL为select c1, c2, c3 from t1 where condi1=1原SQL为Select c1,c2,c3 From t1 Where condi1=1解析后的SQL为select c1, c2, c3 from t1 where condi1=1原SQL为select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2解析后的SQL为select c1, c2, c3 from t1, t2 where condi3=3 or condi4=5 order by o1, o2原SQL为Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2解析后的SQL为select c1, c2, c3 from t1, t2 where condi3=3 or condi4=5 order by o1, o2原SQL为select c1,c2,c3 from t1,t2,t3 wher www.hnnedu.com e condi1=5 and condi6=6 or condi7=7 group by g1,g2解析后的SQL为select c1, c2, c3 from t1, t2, t3 where condi1=5 and condi6=6 or condi7=7 group by g1, g2原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2解析后的SQL为select c1, c2, c3 from t1, t2, t3 where condi1=5 and condi6=6 or condi7=7 group by g1, g2原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3解析后的SQL为select c1, c2, c3 from t1, t2, t3 where condi1=5 and condi6=6 or condi7=7 group by g1, g2, g3 order by g2, g3使用的类SqlParser,你可以拷贝下来使用之:package com.sitinspring.common.sqlFormatter;import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * SQL语句解析器类 * @author: sitinspring(junglesong@gmail.com) * @date: 2008-3-12 */public class SqlParser{ /** * 逗号 */ private static final String Comma = ","; /** * 四个空格 */ private static final String FourSpace = " "; /** * 是否单行显示字段,表,条件的标识量 */ private static boolean isSingleLine=true; /** * 待解析的SQL语句 */ private String sql; /** * SQL中选择的列 */ private String cols; /** * SQL中查找的表 */ private String tables; /** * 查找条件 */ private String conditions; /** * Group By的字段 */ private String groupCols; /** * Order by的字段 */ private String orderCols; /** * 构造函数 * 功能:传入构造函数,解析成字段,表,条件等 * @param sql:传入的SQL语句 */ public SqlParser(String sql){ this.sql=sql.trim();

谁能讲讲sql硬软解析的区别

Oracle SQL的硬解析和软解析 

我们都知道在Oracle中每条SQL语句在执行之前都需要经过解析,这里面又分为软解析和硬解析。在Oracle中存在两种类型的SQL语句,一类为 DDL语句(数据定义语言),他们是从来不会共享使用的,也就是每次执行都需要进行硬解析。还有一类就是DML语句(数据操纵语言),他们会根据情况选择要么进行硬解析,要么进行软解析。

DML:INSERT,UPDATE,DELETE,SELECT

DDL:CREATE,DROP,ALTER 

一.  SQL 解析过程

Oracle对此SQL将进行几个步骤的处理过程:

1、语法检查(syntax check): 检查此sql的拼写是否语法。

2、语义检查(semantic check): 诸如检查sql语句中的访问对象是否存在及该用户是否具备相应的权限。

3、对sql语句进行解析(prase): 利用内部算法对sql进行解析,生成解析树(parse tree)及执行计划(execution plan)。

4、执行sql,返回结果(execute and return)

二. 解析过程详解

2.1  语法检测

判断一条SQL语句的语法是否符合SQL的规范,比如执行:

SQL》 selet * from emp;

我们就可以看出由于Select关键字少了一个“c”,这条语句就无法通过语法检验的步骤了。

2.2 语义检查

语法正确的SQL语句在解析的第二个步骤就是判断该SQL语句所访问的表及列是否准确?用户是否有权限访问或更改相应的表或列? 比如如下语句:

SQL》 select * from emp;

select * from emp

*

ERROR at line 1:

ORA-00942: table or view does not exist

由于查询用户没有可供访问的emp对象,因此该SQL语句无法通过语义检查。

2.3 解析(Parse)

2.3.1 Parse主要分为三种:

1、Hard Parse (硬解析)

2、Soft Parse (软解析)

3、Soft Soft Parse(好像有些资料中并没有将这个算在其中)

Hard Parse: 就是上面提到的对提交的Sql完全重新从头进行解析(当在Shared Pool中找不到时候将会进行此操作),总共有一下5个执行步骤:

1:语法分析

2:权限与对象检查

3: 在共享池中检查是否有完全相同的之前完全解析好的. 如果存在,直接跳过4和5,运行Sql, 此时算soft parse.

4:选择执行计划

5:产生执行计划

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

Soft Parse: 就如果是在Shared Pool中找到了与之完全相同的Sql解析好的结果后会跳过Hard Parse中的后面的两个步骤。

Soft Soft Parse: 实际上是当设置了session_cursor_cache这个参数之后,Cursor被直接Cache在当前Session的PGA中的,在解析的时候只需要对其语法分析、权限对象分析之后就可以转到PGA中查找了,如果发现完全相同的Cursor,就可以直接去取结果了,也就就是实现了 Soft Soft Parse.

2.3.2 解析的步骤可以分为两个步骤:

1) 验证SQL语句是否完全一致。

在这个步骤中,Oracle将会对传递进来的SQL语句使用HASH函数运算得出HASH值,再与共享池中现有语句的HASH值进行比较看是否一一对应。现有数据库中SQL语句的HASH值我们可以通过访问vsqlarea、v$sqltext等数据字典中的HASH_VALUE列查询得出。

如果SQL语句的HASH值一致,那么ORACLE事实上还需要对SQL语句的语义进行再次检测,以决定是否一致。那么为什么Oracle需要再次对语句文本进行检测呢?不是SQL语句的HASH值已经对应上了?事实上就算是SQL语句的HASH值已经对应上了,并不能说明这两条SQL语句就已经可以共享了。

例如:假如用户SYS有自己的一张表EMP,他要执行查询语句:select * from emp; 用户SYSTEM也有一张EMP表,同样要查询select * from emp;这样他们两条语句在文本上是一模一样的,他们的HASH值也会一样,但是由于涉及到查询的相关表不一样,他们事实上是无法共享的. 

SQL》 conn / as sysdba

已连接。

SQL》 show user

USER 为 "SYS"

SQL》  create table emp ( x int ) ;

表已创建。

SQL》 select * from emp;

未选定行

SQL》 conn system/admin;

已连接。

SQL》  create table emp ( x int );

表已创建。

SQL》 select * from emp;

未选定行

SQL》 select address,hash_value, executions, sql_text from v$sql where upper(sql_text) like ’SELECT * FROM EMP%’;

ADDRESS      HASH_VALUE  EXECUTIONS    SQL_TEXT                                                                

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

2769AE64    1745700775     1         select * from emp                                                                                                                         

2769AE64    1745700775     1         select * from emp                                                    

2 rows selected.

从结果可以看到这2个查询的语句文本和HASH值都是一样的,但是由于查询的对象不同,是无法共享的,不同情况的语句还是需要硬解析的。因此在检查共享池共同SQL语句的时候,是需要根据具体情况而定的。

可以进一步查询v$sql_shared_cursor以得知SQL为何不能共享的原因:

SQL》select address,auth_check_mismatch,translation_mismatch,optimizer_mismatch 

from v$sql_shared_cursor where address in ( 

select address from v$sql where upper(sql_text) like ’SELECT * FROM EMP%’ )  

ADDRESS     A T O

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

2769AE64     N N N

2769AE64     Y Y N

TRANSLATION_MISMATCH 表示SQL游标涉及到的数据对象是不同的;

AUTH_CHECK_MISMATCH 表示对同样一条SQL语句转换是不匹配的。

optimizer_mismatch 表示会话的优化器环境是不同的。

2)  验证SQL语句执行环境是否相同

比如同样一条SQL语句,一个查询会话加了/*+ first_rows */的HINT,另外一个用户加/*+ all_rows */的HINT,他们就会产生不同的执行计划,尽管他们是查询同样的数据。

通过如上检查以后,如果SQL语句是一致的,那么就会重用原有SQL语句的执行计划和优化方案,也就是我们通常所说的软解析。如果SQL语句没有找到同样的副本,那么就需要进行硬解析了。

Oracle根据提交的SQL语句再查询相应的数据对象是否有统计信息。如果有统计信息的话,那么CBO将会使用这些统计信息产生所有可能的执行计划(可能多达成千上万个)和相应的Cost,最终选择Cost最低的那个执行计划。如果查询的数据对象无统计信息,则按RBO的默认规则选择相应的执行计划。这个步骤也是解析中最耗费资源的,因此我们应该极力避免硬解析的产生。至此,解析的步骤已经全部完成,Oracle将会根据解析产生的执行计划执行SQL语句和提取相应的数据。 

2.4  执行sql,返回结果(execute and return)

三.  绑定变量  

使用了Bind Var能提高性能主要是因为这样做可以尽量避免不必要的硬分析(Hard Parse)而节约了时间,同时节约了大量的CPU资源。

当一个Client提交一条Sql给Oracle后,Oracle 首先会对其进行解析(Parse),然后将解析结果提交给优化器(Optimiser)来进行优化而取得Oracle认为的最优的Query Plan,然后再按照这个最优的Plan来执行这个Sql语句(当然在这之中如果只需要软解析的话会少部分步骤)。

但是,当Oracle接到 Client提交的Sql后会首先在共享池(Shared Pool)里面去查找是否有之前已经解析好的与刚接到的这一个Sql完全相同的Sql(注意这里说的是完全相同,既要求语句上的字符级别的完全相同,又要求涉及的对象也必须完全相同)。当发现有相同的以后解析器就不再对新的Sql在此解析而直接用之前解析好的结果了。这里就节约了解析时间以及解析时候消耗的CPU资源。尤其是在OLTP中运行着的大量的短小Sql,效果就会比较明显了。因为一条两条Sql的时间可能不会有多少感觉,但是当量大了以后就会有比较明显的感觉了。

SQL如何动态的解析XML

***隐藏网址***DECLARE @ItemTable TABLE(ItemNumber INT PRIMARY KEY,ItemDescription NVARCHAR(300))SET @ItemMessage=N’《ItemList》 《Item》     《ItemNumber》1《/ItemNumber》     《ItemDescription》XBox 360,超值《/ItemDescription》 《/Item》 《Item》     《ItemNumber》2《/ItemNumber》     《ItemDescription》Windows Phone7,快来尝鲜吧《/ItemDescription》 《/Item》 《/ItemList》’INSERT INTO @ItemTable ( ItemNumber, ItemDescription ) SELECT T.c.value(’(ItemNumber/text())’,’INT’), T.c.value(’(ItemDescription/text())’,’NVARCHAR(300)’) FROM @ItemMessage.nodes(’/ItemList/Item’) AS T(c)SELECT ItemNumber, ItemDescription FROM @ItemTable

***隐藏网址***DECLARE @ItemTable TABLE(ItemNumber INT PRIMARY KEY,ItemDescription NVARCHAR(300))***隐藏网址***《Item》     《ItemNumber》1《/ItemNumber》     《ItemDescription》XBox 360,超值《/ItemDescription》 《/Item》 《Item》     《ItemNumber》2《/ItemNumber》     《ItemDescription》Windows Phone7,快来尝鲜吧《/ItemDescription》 《/Item》 《/ItemList》’***隐藏网址***INSERT INTO @ItemTable ( ItemNumber, ItemDescription ) SELECT T.c.value(’(ItemNumber/text())’,’INT’), T.c.value(’(ItemDescription/text())’,’NVARCHAR(300)’) FROM @ItemMessage.nodes(’/ItemList/Item’) AS T(c)SELECT ItemNumber, ItemDescription FROM @ItemTable

关于SQL的解析

注,为了逻辑清晰,分解成多条SQL中1、1.1, 先按客户进行广告收入进行统计---大段的SQL 代码居然无法提交:(而且,现在器已经无法插入代码了,百度问答实在太烂了!

怎样判断一个SQL语句是硬解析还是软解析的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于怎样判断一个SQL语句是硬解析还是软解析、怎样判断一个SQL语句是硬解析还是软解析的信息别忘了在本站进行查找哦。

怎样判断一个SQL语句是硬解析还是软解析?Sql语句解析过程

本文编辑:admin
Copyright © 2022 All Rights Reserved 威海上格软件有限公司 版权所有

鲁ICP备20007704号

Thanks for visiting my site.