sql查询语句优化,几个常用的SQL优化方面的语句_MySQL
sql查询语句优化,几个常用的SQL优化方面的语句_MySQL详细介绍
本文目录一览: SQL数据库优化的方法有哪些?
在进行软件开发过程中,数据库的使用是非常重要的,但是数据库有很多种,不同数据库的使用方法是不同的。进行软件开发过程中,至少需要掌握一种数据库的使用方法。SQL数据库语法简单、操作方便和高效,是很多人最优的选择,但是SQL语句会受到不同数据库功能的影响,在计算时间和语言的效率上面需要进行优化,根据实际情况进行调整。下面电脑培训为大家介绍SQL数据库的优化方法。
一、适当的索引
索引基本上是一种数据结构,有助于加速整个数据检索过程。唯一索引是创建不重叠的数据列的索引。正确的索引可以更快地访问数据库,但是索引太多或没有索引会导致错误的结果。IT培训认为如果没有索引,处理速度会变得非常慢。
二、仅索引相关数据
指定需要检索数据的精度。使用命令*和LIMIT代替SELECT*。调整数据库时,必须使用所需的数据集而不是整个数据集,尤其是当数据源非常大时,指定所需的数据集,能够节省大部分时间。
三、根据需求使用或避免临时表
如果代码可以用简单的方式编写,那么永远不要使临时表变得复杂。当然,如果数据具有需要多个查询的特定程序,北大青鸟建议在这种情况下,使用临时表。临时表通常由子查询交替。
四、避免编码循环
避免编码循环是非常重要的,因为它会减慢整个序列的速度。通过使用具有单行的唯一UPDATE或INSERT命令来避免编码循环,并且昌平镇北大青鸟发现WHERE命令能够确保存储的数据不被更新,这样能够方便在找到匹配和预先存在的数据时被找到。
【基于ORACLE数据库的SQL语句优化分析】 数据库查询语句的优化
【摘 要】 随着数据库应用范围及规模的不断扩大,数据库的性能问题逐渐显现,优化数据库有助于维持系统的稳定性以及运行的高效性。本文主要依据笔者在实际工作中的精英,对SQL语句优化的目的、SQL语句优化技术及原则进行全面分析和阐述。
【关键词】 ORACLE数据库;SQL语句;优化
1前言
随着现代化信息技术的迅猛发展,互联网应用的日益普及,数据库技术的影响力越来越大。作为信息系统管理的核心,数据库的主要操作就是查询,数据库的应用效率在很大程度上是由查询速度决定的,特别是对于规模较大的数据库而言,查询速度十分关键。查询速度在SQL语句中占有很大比重,所以,通过对查询语句进行优化有助于促进应用系统性能及效率的进一步提升。
2SQL语句优化分析
2.1SQL语句优化的目的
对于一个数据库而言,在确保设计无误的前提下,要想避免出现性能问题必须确保其拥有合理的SQL语句结构。最简单的数据库寻找数据路径是对SQL语句进行调整,ORACLE数据库性能提升的主要途径就是对SQL语句进行适当的调整。从本质上讲,SQL语句优化就是确保所使用的语句可以被优化器识别,对索引进行有效利用以便控制表扫描的I/O次数,有效防止出现表搜索。用高性能的SQL语句替代低性能的SQL语句,确定最佳的数据查找路径,尽可能使CPU时间与I/O时间保持平衡是进行优化的主要目的。在对SQL语句进行优化的过程中,以系统需求为依据确定最有可能实现性能提升的语句并进行优化。
2.2SQL语句优化技术及原则
当数据量积累到一定程度之后,对于数据库全表SQL语句进行一次扫描,若查询策略较好,一般只用几秒钟,但如果SQL语句性能较低,就需要用几分钟甚至更多时间。从这点不难看出,SQL语句性能对于查询速度具有极大的影响,所以,对于应用系统而言,不仅能满足功能的实现,还要保证SQL语句的质量。
(1)采取适宜的索引。为达到优化查询的目的,一项重要工作就是确定相适应的索引,并严格依照原则加以使用,与此同时,为有效控制I/O竞争,不可以在同一个磁盘中同时建立索引和用户表空间。
语句1:SELECT CUS_NO, CUS_NAME FROM CUSTOMER WHERE CUS_NO NOT IN
(SELECT CUS_NO FROM SERVICE);
语句2: SELECT CUS_NO, CUS_NAME FROM CUSTOMER WHERE NOT EXISTS
(SELECT * FROM SERVICE WHERE SERVICE.CUS_NO=CUSTOMER.CUS_NO);
上述两个语句可以达到一致的查询结果,对二者进行对比,当执行语句1时,由于ORACLE未利用CUSTOMER 表上CUS_NO索引,所以就会扫描整表,在执行语句2的过程中,ORACLE所扫描的只是CUSTOMER 表子查询中的联合查询,并且使用了CUS_NO索引,因此,在执行效率方面明显优于前者。
(2)避免在SELECT子句中出现“*”。ORACLE在进行解析时,需要按照一定顺序对“*”进行转换,该项转换工作的进行需要对数据库的数据字典进行查询,势必需要花费较多的时间,这样就会导致较低的效率,所以,要避免在SELECT子句中出现“*”。
(3)如果必要可以利用COMMIT提交事务。ORACLE能够自动提交DDL语句,而诸如DML等类型的语句的提交则是通过手动方式或者回滚事务实现的。在编写应用程序的过程中,在操作诸如insert、delete以及update 等较为复杂的语境的时候,利用COMMIT提交事务可以讲会话中持有的锁加以释放,将存在于缓存中的未经修改的数据块进行清除,进而将系统资源予以释放,促进系统性能的进一步提升,因此,如果有必要,可以利用COMMIT对相关事务进行提交。
(4)联合查询连接顺序的确定。如果查询操作涉及到多个表,基础表应当是交叉表,所谓交叉表具体是指被其他表引用的表。连接执行效果在很大程度上受到FROM语句中表的顺序的影响,对于FROM中所包含的表,ORACLE解析器进行处理的顺序是由右至左,SQL语句中所选择的基础表会因优化器的不同而有所区别,在使用CBO的情况下,优化器会对SQL语句中各个表的物理大小以及索引状态进行检查,在此基础上确定一个花费最小的执行路径;在使用RBO的情况下,如果全部的连接条件均有索引与之相对应,那么,FROM子句中位置最后面的表就是基础表。
(5)IN用EXISTS取代。在对数个基础表查询过程中,一般需要进行表的连接。因为利用IN的子查询过程中,ORACLE的扫描对象是全表,因此,出于提高查询效率目的的考虑,应当将IN用EXISTS取代。
(6)在索引列中不使用计算。当通过对函数进行引用在WHERE子句中进行计算的时候,假如索引列只是函数的一部分,优化器就会针对全表进行扫描,而不会使用索引,所以,在索引列中不能使用函数。
3结语
综上所述,随着现代化信息技术的迅猛发展,互联网应用的日益普及,数据库技术的影响力越来越大。在信息量迅速激增的形势下,数据库优化调整成为当前所面临的一大关键性问题,特别是对规模较大的数据库而言,及时进行优化的意义更加倍重大。对于数据库的运行性能而言,最主要的影响因素主要体现在以下几点:数据库系统架构的设计是否合理,资源配置是否科学以及SQL语句编写效率等。笔者从事的是电信企业的运营分析工作,每天都要从数据库取各种数据,可以说是离不开数据库,所以在实践中,我觉得严格遵守SQL语句优化原则及方法,并在实践中及时总结经验教训,可以实现对系统响应时间的有效控制,促进运行效率的提升。
参考文献
[1] 许开宇,胡文骅. 如何提高ORACLE数据库应用程序的性能[J]. 计算机应用与软件. 2002(10)
[2] 郑耀,吴建岚. 基于Oracle数据库的语句优化策略[J]. 信息与电脑(理论版). 2011(07)
[3] 高攀,施蔚然. 基于Oracle数据库的SQL语句优化[J]. 电脑编程技巧与维护. 2010(22)
[4] 钟小权,叶猛. Oracle数据库的SQL语句优化[J]. 计算机与现代化. 2011(03)
作者简介:
王勇军,男,(1981.1-),吉林通化人,就职于中国联合网络通信有限公司长春市分公司,通信工程师,本科,研究方向:SQL使用
(作者单位:中国联合网络通信有限公司长春市分公司)
深入了解优化SQL查询-如何写出高性能SQL语句的具体分析
深入了解优化SQL查询-如何写出高性能SQL语句的具体分析: 1、 首先要搞明白什么叫执行计划? 执行计划是数据库根据SQL语句和相关表的统计信息作出的一个查询方案,这个方案是由查询优化器自动分析产生的,比如一条SQL语句如果用来从一个 10万条记录的表中查1条记录,那查询优化器会选择“索引查找”方式,如果该表进行了归档,当前只剩下5000条记录了,那查询优化器就会改变方案,采用 “全表扫描”方式。 可见,执行计划并不是固定的,它是“个性化的”。产生一个正确的“执行计划”有两点很重要: (1) SQL语句是否清晰地告诉查询优化器它想干什么? (2) 查询优化器得到的数据库统计信息是否是最新的、正确的? 2、 统一SQL语句的写法 对于以下两句SQL语句,程序员认为是相同的,数据库查询优化器认为是不同的。select*from dual select*From dual 其实就是大小写不同,查询分析器就认为是两句不同的SQL语句,必须进行两次解析。生成2个执行计划。所以作为程序员,应该保证相同的查询语句在任何地方都一致,多一个空格都不行! 3、 不要把SQL语句写得太复杂 我经常看到,从数据库中捕捉到的一条SQL语句打印出来有2张A4纸这么长。一般来说这么复杂的语句通常都是有问题的。我拿着这2页长的SQL语句去请教原作者,结果他说时间太长,他一时也看不懂了。可想而知,连原作者都有可能看糊涂的SQL语句,数据库也一样会看糊涂。 一般,将一个Select语句的结果作为子集,然后从该子集中再进行查询,这种一层嵌套语句还是比较常见的,但是根据经验,超过3层嵌套,查询优化器就很容易给出错误的执行计划。因为它被绕晕了。像这种类似人工智能的东西,终究比人的分辨力要差些,如果人都看晕了,我可以保证数据库也会晕的。 另外,执行计划是可以被重用的,越简单的SQL语句被重用的可能性越高。而复杂的SQL语句只要有一个字符发生变化就必须重新解析,然后再把这一大堆垃圾塞在内存里。可想而知,数据库的效率会何等低下。 4、 使用“临时表”暂存中间结果 简化SQL语句的重要方法就是采用临时表暂存中间结果,但是,临时表的好处远远不止这些,将临时结果暂存在临时表,后面的查询就在tempdb中了,这可以避免程序中多次扫描主表,也大大减少了程序执行中“共享锁”阻塞“更新锁”,减少了阻塞,提高了并发性能。 5、 OLTP系统SQL语句必须采用绑定变量select*from orderheader where changetime >'2010-10-20 00:00:01' select*from orderheader where changetime >'2010-09-22 00:00:01' 以上两句语句,查询优化器认为是不同的SQL语句,需要解析两次。如果采用绑定变量select*from orderheader where changetime >@chgtime @chgtime变量可以传入任何值,这样大量的类似查询可以重用该执行计划了,这可以大大降低数据库解析SQL语句的负担。一次解析,多次重用,是提高数据库效率的原则。 6、 绑定变量窥测 事物都存在两面性,绑定变量对大多数OLTP处理是适用的,但是也有例外。比如在where条件中的字段是“倾斜字段”的时候。 “倾斜字段”指该列中的绝大多数的值都是相同的,比如一张人口调查表,其中“民族”这列,90%以上都是汉族。那么如果一个SQL语句要查询30岁的汉族人口有多少,那“民族”这列必然要被放在where条件中。这个时候如果采用绑定变量@nation会存在很大问题。 试想如果@nation传入的第一个值是“汉族”,那整个执行计划必然会选择表扫描。然后,第二个值传入的是“布依族”,按理说“布依族”占的比例可能只有万分之一,应该采用索引查找。但是,由于重用了第一次解析的“汉族”的那个执行计划,那么第二次也将采用表扫描方式。这个问题就是著名的“绑定变量窥测”,建议对于“倾斜字段”不要采用绑定变量。 7、 只在必要的情况下才使用begin tran SQL Server中一句SQL语句默认就是一个事务,在该语句执行完成后也是默认commit的。其实,这就是begin tran的一个最小化的形式,好比在每句语句开头隐含了一个begin tran,结束时隐含了一个commit。 有些情况下,我们需要显式声明begin tran,比如做“插、删、改”操作需要同时修改几个表,要求要么几个表都修改成功,要么都不成功。begin tran 可以起到这样的作用,它可以把若干SQL语句套在一起执行,最后再一起commit。好处是保证了数据的一致性,但任何事情都不是完美无缺的。Begin tran付出的代价是在提交之前,所有SQL语句锁住的资源都不能释放,直到commit掉。 可见,如果Begin tran套住的SQL语句太多,那数据库的性能就糟糕了。在该大事务提交之前,必然会阻塞别的语句,造成block很多。 Begin tran使用的原则是,在保证数据一致性的前提下,begin tran 套住的SQL语句越少越好!有些情况下可以采用触发器同步数据,不一定要用begin tran。 8、 一些SQL查询语句应加上nolock 在SQL语句中加nolock是提高SQL Server并发性能的重要手段,在oracle中并不需要这样做,因为oracle的结构更为合理,有undo表空间保存“数据前影”,该数据如果在修改中还未commit,那么你读到的是它修改之前的副本,该副本放在undo表空间中。这样,oracle的读、写可以做到互不影响,这也是oracle 广受称赞的地方。SQL Server 的读、写是会相互阻塞的,为了提高并发性能,对于一些查询,可以加上nolock,这样读的时候可以允许写,但缺点是可能读到未提交的脏数据。使用 nolock有3条原则。 (1) 查询的结果用于“插、删、改”的不能加nolock ! (2) 查询的表属于频繁发生页分裂的,慎用nolock ! (3) 使用临时表一样可以保存“数据前影”,起到类似oracle的undo表空间的功能, 能采用临时表提高并发性能的,不要用nolock 。 9、 聚集索引没有建在表的顺序字段上,该表容易发生页分裂 比如订单表,有订单编号orderid,也有客户编号contactid,那么聚集索引应该加在哪个字段上呢?对于该表,订单编号是顺序添加的,如果在orderid上加聚集索引,新增的行都是添加在末尾,这样不容易经常产生页分裂。然而,由于大多数查询都是根据客户编号来查的,因此,将聚集索引加在contactid上才有意义。而contactid对于订单表而言,并非顺序字段。 比如“张三”的“contactid”是001,那么“张三”的订单信息必须都放在这张表的第一个数据页上,如果今天“张三”新下了一个订单,那该订单信息不能放在表的最后一页,而是第一页!如果第一页放满了呢?很抱歉,该表所有数据都要往后移动为这条记录腾地方。 SQL Server的索引和Oracle的索引是不同的,SQL Server的聚集索引实际上是对表按照聚集索引字段的顺序进行了排序,相当于oracle的索引组织表。SQL Server的聚集索引就是表本身的一种组织形式,所以它的效率是非常高的。也正因为此,插入一条记录,它的位置不是随便放的,而是要按照顺序放在该放的数据页,如果那个数据页没有空间了,就引起了页分裂。所以很显然,聚集索引没有建在表的顺序字段上,该表容易发生页分裂。 曾经碰到过一个情况,一位哥们的某张表重建索引后,插入的效率大幅下降了。估计情况大概是这样的。该表的聚集索引可能没有建在表的顺序字段上,该表经常被归档,所以该表的数据是以一种稀疏状态存在的。比如张三下过20张订单,而最近3个月的订单只有5张,归档策略是保留3个月数据,那么张三过去的 15张订单已经被归档,留下15个空位,可以在insert发生时重新被利用。在这种情况下由于有空位可以利用,就不会发生页分裂。但是查询性能会比较低,因为查询时必须扫描那些没有数据的空位。 重建聚集索引后情况改变了,因为重建聚集索引就是把表中的数据重新排列一遍,原来的空位没有了,而页的填充率又很高,插入数据经常要发生页分裂,所以性能大幅下降。 对于聚集索引没有建在顺序字段上的表,是否要给与比较低的页填充率?是否要避免重建聚集索引?是一个值得考虑的问题! 10、加nolock后查询经常发生页分裂的表,容易产生跳读或重复读 加nolock后可以在“插、删、改”的同时进行查询,但是由于同时发生“插、删、改”,在某些情况下,一旦该数据页满了,那么页分裂不可避免,而此时nolock的查询正在发生,比如在第100页已经读过的记录,可能会因为页分裂而分到第101页,这有可能使得nolock查询在读101页时重复读到该条数据,产生“重复读”。同理,如果在100页上的数据还没被读到就分到99页去了,那nolock查询有可能会漏过该记录,产生“跳读”。 上面提到的哥们,在加了nolock后一些操作出现报错,估计有可能因为nolock查询产生了重复读,2条相同的记录去插入别的表,当然会发生主键冲突。 11、使用like进行模糊查询时应注意 有的时候会需要进行一些模糊查询比如select*from contact where username like ‘%yue%’ 关键词%yue%,由于yue前面用到了“%”,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%, 12、数据类型的隐式转换对查询效率的影响 sql server2000的数据库,我们的程序在提交sql语句的时候,没有使用强类型提交这个字段的值,由sql server 2000自动转换数据类型,会导致传入的参数与主键字段类型不一致,这个时候sql server 2000可能就会使用全表扫描。Sql2005上没有发现这种问题,但是还是应该注意一下。 13、SQL Server 表连接的三种方式 (1) Merge Join (2) Nested Loop Join (3) Hash Join SQL Server 2000只有一种join方式——Nested Loop Join,如果A结果集较小,那就默认作为外表,A中每条记录都要去B中扫描一遍,实际扫过的行数相当于A结果集行数x B结果集行数。所以如果两个结果集都很大,那Join的结果很糟糕。 SQL Server 2005新增了Merge Join,如果A表和B表的连接字段正好是聚集索引所在字段,那么表的顺序已经排好,只要两边拼上去就行了,这种join的开销相当于A表的结果集行数加上B表的结果集行数,一个是加,一个是乘,可见merge join 的效果要比Nested Loop Join好多了。 如果连接的字段上没有索引,那SQL2000的效率是相当低的,而SQL2005提供了Hash join,相当于临时给A,B表的结果集加上索引,因此SQL2005的效率比SQL2000有很大提高,我认为,这是一个重要的原因。 总结一下,在表连接时要注意以下几点: (1) 连接字段尽量选择聚集索引所在的字段 (2) 仔细考虑where条件,尽量减小A、B表的结果集 (3) 如果很多join的连接字段都缺少索引,而你还在用SQL Server 2000,赶紧升级吧。
如何优化SQL语句(全)
高性能的SQL语句会在软件运行中起到非常重要的作用,下面小编把最近整理的SQL语句优化资料分享给大家。第一:选择最有效率的表名顺序(只在基于规则的seo/' target='_blank'>优化器中有效): ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.第二:WHERE子句中的连接顺序.: ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.第三:SELECT子句中避免使用 ‘ * ‘: ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间第四:减少访问get='_blank'>数据库的次数: ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等;第五:在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次get='_blank'>数据库访问的检索数据量 ,建议值为200第六:使用DECODE函数来减少处理时间: 使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表.第七:整合简单,无关联的get='_blank'>数据库访问: 如果你有几个简单的get='_blank'>数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)第八:删除重复记录: 最高效的删除重复记录方法 ( 因为使用了ROWID)例子: DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO);第九:用TRUNCATE替代DELETE: 当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短. (译者按: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML)第十:尽量多使用COMMIT: 只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少: COMMIT所释放的资源: a. 回滚段上用于恢复数据的信息. b. 被程序语句获得的锁 c. redo log buffer 中的空间 d. ORACLE为管理上述3种资源中的内部花费第十一:用Where子句替换HAVING子句: 避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作. 如果能通过WHERE子句限制记录的数目,那就能减少这方面的开销. (非oracle中)on、where、having这三个都可以加条件的子句中,on是最先执行,where次之,having最后,因为on是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的,where也应该比having快点的,因为它过滤数据后才进行sum,在两个表联接时才用on的,所以在一个表的时候,就剩下where跟having比较了。在这单表查询统计的情况下,如果要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是where可以使用rushmore技术,而having就不能,在速度上后者要慢如果要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的,根据上篇写的工作流程,where的作用时间是在计算之前就完成的,而having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。在多表联接查询时,on比where更早起作用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where进行过滤,然后再计算,计算完后再由having进行过滤。由此可见,要想过滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后再决定放在那里第十二:减少对表的查询: 在含有子查询的SQL语句中,要特别注意减少对表的查询.例子: SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)第十三:通过内部函数提高SQL效率.: 复杂的SQL往往牺牲了执行效率. 能够掌握上面的运用函数解决问题的方法在实际工作中是非常有意义的第十四:使用表的别名(Alias): 当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column上.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.第十五:用EXISTS替代IN、用NOT EXISTS替代NOT IN: 在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(或NOT EXISTS)通常将提高查询的效率. 在子查询中,NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历). 为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)或NOT EXISTS. 例子:(高效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND EXISTS (SELECT ‘X' FROM DEPT WHERE DEPT.DEPTNO = EMP.DEPTNO AND LOC = ‘MELB') (低效)SELECT * FROM EMP (基础表) WHERE EMPNO > 0 AND DEPTNO IN(SELECT DEPTNO FROM DEPT WHERE LOC = ‘MELB')第十六:识别'低效执行'的SQL语句: 虽然目前各种关于SQLseo/' target='_blank'>优化的图形化工具层出不穷,但是写出自己的SQL工具来解决问题始终是一个最好的方法: SELECT EXECUTIONS , DISK_READS, BUFFER_GETS, ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio, ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run, SQL_TEXT FROM V$SQLAREA WHERE EXECUTIONS>0 AND BUFFER_GETS > 0 AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8 ORDER BY 4 DESC;第十七:用索引提高效率: 索引是表的一个概念部分,用来提高检索数据的效率,ORACLE使用了一个复杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. 当ORACLE找出执行查询和Update语句的最佳路径时, ORACLEseo/' target='_blank'>优化器将使用索引. 同样在联结多个表时使用索引也可以提高效率. 另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证.。那些LONG或LONG RAW数据类型, 你可以索引几乎所有的列. 通常, 在大型表中使用索引特别有效. 当然,你也会发现, 在扫描小表时,使用索引同样能提高效率. 虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价. 索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改. 这意味着每条记录的INSERT , DELETE , UPDATE将为此多付出4 , 5 次的磁盘I/O . 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.。定期的重构索引是有必要的.: ALTER INDEX REBUILD第十八:用EXISTS替换DISTINCT: 当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换, EXISTS 使查询更为迅速,因为RDBMS核心模块将在子查询的条件一旦满足后,立刻返回结果. 例子: (低效): SELECT DISTINCT DEPT_NO,DEPT_NAME FROM DEPT D , EMP E WHERE D.DEPT_NO = E.DEPT_NO (高效): SELECT DEPT_NO,DEPT_NAME FROM DEPT D WHERE EXISTS ( SELECT ‘X' FROM EMP E WHERE E.DEPT_NO = D.DEPT_NO);第十九:server/' target='_blank'>sql语句用大写的;因为oracle总是先解析server/' target='_blank'>sql语句,把小写的字母转换成大写的再执行第二十:在java代码中尽量少用连接符“+”连接字符串!第二十一:避免在索引列上使用NOT 通常, 我们要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响. 当ORACLE”遇到”NOT,他就会停止使用索引转而执行全表扫描.第二十二:避免在索引列上使用计算. WHERE子句中,如果索引列是函数的一部分.seo/' target='_blank'>优化器将不使用索引而使用全表扫描. 举例: 低效: SELECT ? FROM DEPT WHERE SAL * 12 > 25000; 高效: SELECT ? FROM DEPT WHERE SAL > 25000/12;第二十三:用>=替代> 高效: SELECT * FROM EMP WHERE DEPTNO >=4 低效: SELECT * FROM EMP WHERE DEPTNO >3 两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录. ======================================== 集成代码生成器 SpringMVC_mybatis or hibernate+ehcache二级缓存_shiro_druid_bootstrap_HTML5 java企业框架tab标签_maven非maven版本 http://my.oschina.net/u/2347562/blog/400728 ========================================第二十四:用UNION替换OR (适用于索引列) 通常情况下, 用UNION替换WHERE子句中的OR将会起到较好的效果. 对索引列使用OR将造成全表扫描. 注意, 以上规则只针对多个索引列有效. 如果有column没有被索引, 查询效率可能会因为你没有选择OR而降低. 在下面的例子中, LOC_ID 和REGION上都建有索引. 高效: SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 UNION SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE REGION = “MELBOURNE” 低效: SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 OR REGION = “MELBOURNE” 如果你坚持要用OR, 那就需要返回记录最少的索引列写在最前面.第二十五:用IN来替换OR 这是一条简单易记的规则,但是实际的执行效果还须检验,在ORACLE8i下,两者的执行路径似乎是相同的. 低效: SELECT?. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30 高效 SELECT? FROM LOCATION WHERE LOC_IN IN (10,20,30);第二十六:避免在索引列上使用IS NULL和IS NOT NULL 避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引.对于单列索引,如果列包含空值,索引中将不存在此记录. 对于复合索引,如果每个列都为空,索引中同样不存在此记录.如果至少有一个列不为空,则记录存在于索引中.举例: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , ORACLE将不接受下一条具有相同A,B值(123,null)的记录(插入). 然而如果所有的索引列都为空,ORACLE将认为整个键值为空而空不等于空. 因此你可以插入1000 条具有相同键值的记录,当然它们都是空! 因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引. 低效: (索引失效) SELECT ? FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL; 高效: (索引有效) SELECT ? FROM DEPARTMENT WHERE DEPT_CODE >=0;第二十七:总是使用索引的第一个列: 如果索引是建立在多个列上, 只有在它的第一个列(leading column)被where子句引用时,seo/' target='_blank'>优化器才会选择使用该索引. 这也是一条简单而重要的规则,当仅引用索引的第二个列时,seo/' target='_blank'>优化器使用了全表扫描而忽略了索引第二十八:用UNION-ALL 替换UNION ( 如果有可能的话): 当SQL 语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序. 如果用UNION ALL替代UNION, 这样排序就不是必要了. 效率就会因此得到提高. 需要注意的是,UNION ALL 将重复输出两个结果集合中相同记录. 因此各位还是要从业务需求分析使用UNION ALL的可行性. UNION 将对结果集合排序,这个操作会使用到SORT_AREA_SIZE这块内存. 对于这块内存的seo/' target='_blank'>优化也是相当重要的. 下面的SQL可以用来查询排序的消耗量 低效: SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95' UNION SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95' 高效: SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95' UNION ALL SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95'第二十九:用WHERE替代ORDER BY: ORDER BY 子句只在两种严格的条件下使用索引. ORDER BY中所有的列必须包含在相同的索引中并保持在索引中的排列顺序. ORDER BY中所有的列必须定义为非空. WHERE子句使用的索引和ORDER BY子句中所使用的索引不能并列. 例如: 表DEPT包含以下列: DEPT_CODE PK NOT NULL DEPT_DESC NOT NULL DEPT_TYPE NULL 低效: (索引不被使用) SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE 高效: (使用索引) SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0第三十:避免改变索引列的类型.: 当比较不同数据类型的数据时, ORACLE自动对列进行简单的类型转换. 假设 EMPNO是一个数值类型的索引列. SELECT ? FROM EMP WHERE EMPNO = ‘123' 实际上,经过ORACLE类型转换, 语句转化为: SELECT ? FROM EMP WHERE EMPNO = TO_NUMBER(‘123') 幸运的是,类型转换没有发生在索引列上,索引的用途没有被改变. 现在,假设EMP_TYPE是一个字符类型的索引列. SELECT ? FROM EMP WHERE EMP_TYPE = 123 这个语句被ORACLE转换为: SELECT ? FROM EMP WHERETO_NUMBER(EMP_TYPE)=123 因为内部发生的类型转换, 这个索引将不会被用到! 为了避免ORACLE对你的SQL进行隐式的类型转换, 最好把类型转换用显式表现出来. 注意当字符和数值比较时, ORACLE会优先转换数值类型到字符类型第三十一:需要当心的WHERE子句: 某些SELECT 语句中的WHERE子句不使用索引. 这里有一些例子. 在下面的例子里, (1)‘!=' 将不使用索引. 记住, 索引只能告诉你什么存在于表中, 而不能告诉你什么不存在于表中. (2) ‘||'是字符连接函数. 就象其他函数那样, 停用了索引. (3) ‘+'是数学函数. 就象其他数学函数那样, 停用了索引. (4)相同的索引列不能互相比较,这将会启用全表扫描.第三十二:a. 如果检索数据量超过30%的表中记录数.使用索引将没有显著的效率提高. b. 在特定情况下, 使用索引也许会比全表扫描慢, 但这是同一个数量级上的区别. 而通常情况下,使用索引比全表扫描要块几倍乃至几千倍!第三十三:避免使用耗费资源的操作: 带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL语句会启动SQL引擎 执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序. 通常, 带有UNION, MINUS , INTERSECT的SQL语句都可以用其他方式重写. 如果你的get='_blank'>数据库的SORT_AREA_SIZE调配得好, 使用UNION , MINUS, INTERSECT也是可以考虑的, 毕竟它们的可读性很强第三十四:seo/' target='_blank'>优化GROUP BY: 提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多. 低效: SELECT JOB , AVG(SAL) FROM EMP GROUP by JOB HAVING JOB = ‘PRESIDENT' OR JOB = ‘MANAGER' 高效: SELECT JOB , AVG(SAL) FROM EMP WHERE JOB = ‘PRESIDENT' OR JOB = ‘MANAGER' GROUP by JOB以上总结了三十四对如何优化SQL语句做了总结,希望大家喜欢。 您可能感兴趣的文章:浅谈MySQL中优化sql语句查询常用的30种方法sql语句优化之用EXISTS替代IN、用NOT EXISTS替代NOT IN的语句SQL语句优化方法30例(推荐)如何优化SQL语句的心得浅谈SQL 语句优化方法30例通过分析SQL语句的执行计划优化SQL常用SQL语句优化技巧总结【经典】SQL语句优化提高数据库性能SQL语句性能优化(续)sql语句优化的一般步骤详解
sql语句查询,多字段like模糊查询优化
首先需要开启数据库管理工具,打开SQL语言编写窗体。如果我们知道某字段的开头部分,我们可以用like‘xx%selectTOP10*fromCK_ATEwhereModellikePSM24W%。
初始化SqlCommand、SqlConnection,获取数据表至DataTable,查询多次,本地缓冲,效率高点。
进行SQL性能优化的方法:SQL语句不要写的太复杂。一个SQL语句要尽量简单,不要嵌套太多层。使用『临时表』缓存中间结果。
SQL模糊查询,使用like比较关键字,加上SQL里的通配符,请参考以下:LIKEMc%将搜索以字母Mc开头的所有字符串(如McBadden)。LIKE%inger将搜索以字母inger结尾的所有字符串(如Ringer、Stringer)。
用Like子句。比如:Select*from[TableName]where[名称]Like%SQL%and[简介]like%Software%这就是查询[名称]字段中包含“SQL”、并且[简介]字段中包含“Software”的记录。
【查询优化】怎样用SQL语句查看查询的性能指标
--显示有关由Transact-SQL 语句生成的磁盘活动量的信息SET STATISTICS IO ON--关闭有关由Transact-SQL 语句生成的磁盘活动量的信息SET STATISTICS IO OFF显示的信息如下:(SQL语句为:select * from note500)其中:扫描计数:在查询中涉及到的表被访问的次数;逻辑读取:从数据缓冲中读取的数据页数;物理读取:从物理磁盘中往缓冲读取的数据页数;预读:根据执行计划从物理磁盘中往缓冲读取的数据页数;其中对于首次查询一般情况下会有一下关系:逻辑读取=物理读取+预读(其中的具体联系,由于已经在之前的博客文章中提到,就不再详细说明(文章名为【查询优化】MSSQL查询执行流程))同理,后面的lob逻辑读取、物理读取、预读概念理解差不多,只是是对相应表进行更新或插入操作时体现。对于扫描计数,以上图片的查询没有连接查询,因此意义不大。不过,如果连接查询来说,特别是循环查询那种,比如说自连接,如果循环次数越多,则扫描次数也就越多,则会使得查询的效率越低。这是扫描计数是一个比较重要的性能体现参数。对于逻辑读取,由于SQLSERVER中对数据进行任何操作都要把数据读入到缓冲当中,如果逻辑读取的页数越多,则查询的性能越低。为此,逻辑读取一般都是查询性能体现的一个重要参数。二、SET STATISTICS TIME(SQL Server解析和编译时间)面显示的信息表明,执行这次查询使用了多少CPU运行时间和运行查询使用了多少时间。CPU运行时间是对运行查询所需要的CPU资源的一种相对稳定的测量方法,与CPU的忙闲程度没有关系。但是,每次运行查询时这一数字也会有所不同,只是变化的范围没有总时间变化大。总时间是对查询执行所需要的时间(不计算阻塞或读数据的时间),由于服务器上的负载是在不断变化的,因此这一数据的变化范围有时会相当地大。总的来说,量化地来看一个查询语句的性能可以在几个参数进行比较:1、CPU时间。比较查询所要占用的CPU资源时间;2、I/O。可以比较查询的循环扫描次数和逻辑读取的数据量;【查询优化】怎样用SQL语句查看查询的性能指标标签:
mysql-sql语句的查询优化,各位看看可以怎么优化,新人初学,SQL有点复杂,压力山大。。。。。
mysql优化sql 如下 项目用的是 mysql 是项目的查询SQL语句, 查询结果为 88 的竟然要1分40秒, 结果为5的要 2秒,SQL语句不是我写的,大家看看有什么地方可以优化的,想要优化查询速度的话,可以从哪方面入手修改。 SELECT COUNT(DISTINCT ttsp.id) AS postpone_count, ttp.task_document_id AS task_document_id, ttm.id AS attention_id, tt.company_id, tt.create_by, ts.name AS principal, ts.staff_id AS principal_id, tt.postpone_time, tt.subtask_bind_step_id, tt.current_task_step_id, tt.create_time, tts.task_step_id AS has_taskstep, tts2.current_task_step, tt.po_predict_work_load, tt.task_priority, tt.expect_end_time, tts2.executor, tt.start_time, tt.end_time, tt.type, tta.task_annex_id AS annex, tt.task_id AS id, tt.title AS NAME, CASE WHEN ( (SELECT COUNT(*) FROM t_task_step WHERE task_id = tt.task_id AND del_flag = 0) > 0 ) THEN 'closed' WHEN ( (SELECT COUNT(*) FROM t_task WHERE pid = tt.task_id AND del_flag = 0) > 0 ) THEN 'closed' ELSE 'open' END AS state, '3' AS style, tt.author AS task_author, tt.work_load AS task_work_load, tm.comment AS content_comment, tn.comment AS time_comment, tq.comment AS other_comment, tnn.comment AS inner_comment, CONCAT(tt.task_id, '_t') AS id_type, SUM(tw.workload) count_workload, tt.pid, CASE WHEN tt.task_priority = '1' THEN 'task-emergency' WHEN tt.task_priority = '2' THEN 'task-imprtant' WHEN tt.task_priority = '3' THEN 'task-general' ELSE 'task-normal' END AS iconCls FROM t_task tt LEFT JOIN t_task_step tts ON ( tt.task_id = tts.task_id AND tts.del_flag = '0' ) LEFT JOIN t_workload tw ON ( tts.task_step_id = tw.task_step_id AND tw.del_flag = '0' ) LEFT JOIN t_task_content ttc ON ( tt.task_id = ttc.task_id AND ttc.del_flag = '0' ) LEFT JOIN (SELECT * FROM t_task_annex ORDER BY task_annex_id DESC) tta ON ( tt.task_id = tta.task_id AND tta.del_flag = '0' AND tta.annex IS NOT NULL ) LEFT JOIN t_project tp ON tt.project_id = tp.project_id LEFT JOIN t_company tco ON tt.company_id = tco.company_id LEFT JOIN (SELECT foreign_id, COMMENT, create_time FROM t_comment WHERE del_flag = '0' AND TYPE = 2 AND comment_type = 0 ORDER BY create_time DESC LIMIT 0, 1) AS tm ON tt.task_id = tm.foreign_id LEFT JOIN (SELECT foreign_id, COMMENT, create_time FROM t_comment WHERE del_flag = '0' AND TYPE = 2 AND comment_type = 1 ORDER BY create_time DESC LIMIT 0, 1) AS tn ON tt.task_id = tn.foreign_id LEFT JOIN (SELECT foreign_id, COMMENT, create_time FROM t_comment WHERE del_flag = '0' AND TYPE = 2 AND comment_type = 2 ORDER BY create_time DESC LIMIT 0, 1) AS tq ON tt.task_id = tq.foreign_id LEFT JOIN (SELECT foreign_id, COMMENT, create_time FROM t_comment WHERE del_flag = '0' AND TYPE = 2 AND comment_type = 3 ORDER BY create_time DESC LIMIT 0, 1) AS tnn ON tt.task_id = tnn.foreign_id LEFT JOIN (SELECT task_step_id, TYPE AS current_task_step, to_staff AS executor, to_staff_email AS executor_email FROM t_task_step WHERE del_flag = '0') tts2 ON tts2.task_step_id = tt.current_task_step_id LEFT JOIN t_staff ts ON (tt.executor = ts.staff_id) LEFT JOIN (SELECT ttp.task_id, GROUP_CONCAT(producttype_id SEPARATOR ',') AS producttype_id, task_document_id FROM (SELECT ttp.producttype_id, ttp.task_id, ttdl.task_document_id FROM t_task_producttype_link ttp LEFT JOIN (SELECT producttype_id, GROUP_CONCAT(id SEPARATOR ',') AS task_document_id FROM t_task_document_type_link GROUP BY producttype_id) ttdl ON ttp.producttype_id = ttdl.producttype_id) ttp GROUP BY task_id) ttp ON ttp.task_id = tt.task_id LEFT JOIN t_task_step_postpone_history ttsp ON ttsp.foreign_id = tt.task_id AND ttsp.type = 0 AND ttsp.del_flag = 0 LEFT JOIN (SELECT * FROM t_task_myattention WHERE user_id = '202b293f-da58-4cd3-b12d-40e4f9ce0d2c') ttm ON ttm.task_id = tt.task_id WHERE tco.del_flag = '0' AND tt.del_flag = '0' AND tp.del_flag = '0' AND tt.project_id = 44 AND tt.pid IS NULL GROUP BY tt.task_id ORDER BY tt.task_id DESC 这是 explain的查询结果
几个常用的SQL优化方面的语句_MySQL
bitsCN.com以下是几个常用的SQL语句优化方面的语句,记录下来,避免忘记。虽然通过sqlprofiler也能得到这些类似数据,不过对于单条查询语句而已,这样使用方便很多1.记录语句的查询时间 SET STATISTICS TIME ON GO SELECT * FROM table GO SET STATISTICS TIME OFF GO2.记录语句的读取次数 SET STATISTICS IO ON GO SELECT * FROM table GO SET STATISTICS IO OFF GO 3. 返回该表的空间大小 sp_spaceused tablebitsCN.com
通过分析SQL语句的执行计划优化SQL(三)
第 章 SQL语句处理的过程 在调整之前我们需要了解一些背景知识 只有知道这些背景知识 我们才能更好的去调整sql语句 本节介绍了SQL语句处理的基本过程 主要包括 · 查询语句处理 · DML语句处理(insert update delete) · DDL 语句处理(create drop alter ) · 事务控制(mit rollback) SQL 语句的执行过程(SQL Statement Execution) 图 概要的列出了处理和运行一个sql语句的需要各个重要阶段 在某些情况下 Oracle运行sql的过程可能与下面列出的各个阶段的顺序有所不同 如DEFINE阶段可能在FETCH阶段之前 这主要依赖你如何书写代码 对许多oracle的工具来说 其中某些阶段会自动执行 绝大多数用户不需要关心各个阶段的细节问题 然而 知道执行的各个阶段还是有必要的 这会帮助你写出更高效的SQL语句来 而且还可以让你猜测出性能差的SQL语句主要是由于哪一个阶段造成的 然后我们针对这个具体的阶段 找出解决的办法 图 SQL语句处理的各个阶段 DML语句的处理 本节给出一个例子来说明在DML语句处理的各个阶段到底发生了什么事情 假设你使用Pro*C程序来为指定部门的所有职员增加工资 程序已经连到正确的用户 你可以在你的程序中嵌入如下的SQL语句 EXEC SQL UPDATE employees SET salary = * salary WHERE department_id = :var_department_id; var_department_id是程序变量 里面包含部门号 我们要修改该部门的职员的工资 当这个SQL语句执行时 使用该变量的值 每种类型的语句都需要如下阶段 · 第 步: Create a Cursor 创建游标 · 第 步: Parse the Statement 分析语句 · 第 步: Bind Any Variables 绑定变量 · 第 步: Run the Statement 运行语句 · 第 步: Close the Cursor 关闭游标 如果使用了并行功能 还会包含下面这个阶段 · 第 步: Parallelize the Statement 并行执行语句 如果是查询语句 则需要以下几个额外的步骤 如图 所示 · 第 步: Describe Results of a Query 描述查询的结果集 · 第 步: Define Output of a Query 定义查询的输出数据 · 第 步: Fetch Rows of a Query 取查询出来的行 下面具体说一下每一步中都发生了什么事情 第 步: 创建游标(Create a Cursor) 由程序接口调用创建一个游标(cursor) 任何SQL语句都会创建它 特别在运行DML语句时 都是自动创建游标的 不需要开发人员干预 多数应用中 游标的创建是自动的 然而 在预编译程序(pro*c)中游标的创建 可能是隐含的 也可能显式的创建 在存储过程中也是这样的 第 步:分析语句(Parse the Statement) 在语法分析期间 SQL语句从用户进程传送到Oracle SQL语句经语法分析后 SQL语句本身与分析的信息都被装入到共享SQL区 在该阶段中 可以解决许多类型的错误 语法分析分别执行下列操作 l 翻译SQL语句 验证它是合法的语句 即书写正确l 实现数据字典的查找 以验证是否符合表和列的定义l 在所要求的对象上获取语法分析锁 使得在语句的语法分析过程中不改变这些对象的定义l 验证为存取所涉及的模式对象所需的权限是否满足l 决定此语句最佳的执行计划l 将它装入共享SQL区l 对分布的语句来说 把语句的全部或部分路由到包含所涉及数据的远程节点 以上任何一步出现错误 都将导致语句报错 中止执行 只有在共享池中不存在等价SQL语句的情况下 才对SQL语句作语法分析 在这种情况下 数据库内核重新为该语句分配新的共享SQL区 并对语句进行语法分析 进行语法分析需要耗费较多的资源 所以要尽量避免进行语法分析 这是优化的技巧之一 语法分析阶段包含了不管此语句将执行多少次 而只需分析一次的处理要求 Oracle只对每个SQL语句翻译一次 在以后再次执行该语句时 只要该语句还在共享SQL区中 就可以避免对该语句重新进行语法分析 也就是此时可以直接使用其对应的执行计划对数据进行存取 这主要是通过绑定变量(bind variable)实现的 也就是我们常说的共享SQL 后面会给出共享SQL的概念 虽然语法分析验证了SQL语句的正确性 但语法分析只能识别在SQL语句执行之前所能发现的错误(如书写错误 权限不足等) 因此 有些错误通过语法分析是抓不到的 例如 在数据转换中的错误或在数据中的错(如企图在主键中插入重复的值)以及死锁等均是只有在语句执行阶段期间才能遇到和报告的错误或情况 查询语句的处理 查询与其它类型的SQL语句不同 因为在成功执行后作为结果将返回数据 其它语句只是简单地返回成功或失败 而查询则能返回一行或许多行数据 查询的结果均采用表格形式 结果行被一次一行或者批量地被检索出来 从这里我们可以得知批量的fetch数据可以降低网络开销 所以批量的fetch也是优化的技巧之一 有些问题只与查询处理相关 查询不仅仅指SELECT语句 同样也包括在其它SQL语句中的隐含查询 例如 下面的每个语句都需要把查询作为它执行的一部分 INSERT INTO table SELECT UPDATE table SET x = y WHERE DELETE FROM table WHERE CREATE table AS SELECT 具体来说 查询· 要求读一致性· 可能使用回滚段作中间处理· 可能要求SQL语句处理描述 定义和取数据阶段 第 步: 描述查询结果(Describe Results of a Query) 描述阶段只有在查询结果的各个列是未知时才需要 例如 当查询由用户交互地输入需要输出的列名 在这种情况要用描述阶段来决定查询结果的特征(数据类型 长度和名字) 第 步: 定义查询的输出数据(Define Output of a Query) 在查询的定义阶段 你指定与查询出的列值对应的接收变量的位置 大小和数据类型 这样我们通过接收变量就可以得到查询结果 如果必要的话 Oracle会自动实现数据类型的转换 这是将接收变量的类型与对应的列类型相比较决定的 第 步: 绑定变量(Bind Any Variables) 此时 Oracle知道了SQL语句的意思 但仍没有足够的信息用于执行该语句 Oracle 需要得到在语句中列出的所有变量的值 在该例中 Oracle需要得到对department_id列进行限定的值 得到这个值的过程就叫绑定变量(binding variables) 此过程称之为将变量值捆绑进来 程序必须指出可以找到该数值的变量名(该变量被称为捆绑变量 变量名实质上是一个内存地址 相当于指针) 应用的最终用户可能并没有发觉他们正在指定捆绑变量 因为Oracle 的程序可能只是简单地指示他们输入新的值 其实这一切都在程序中自动做了 因为你指定了变量名 在你再次执行之前无须重新捆绑变量 你可以改变绑定变量的值 而Oracle在每次执行时 仅仅使用内存地址来查找此值 如果Oracle 需要实现自动数据类型转换的话(除非它们是隐含的或缺省的) 你还必须对每个值指定数据类型和长度 关于这些信息可以参考oracle的相关文档 如Oracle Call Interface Programmer s Guide 第 步: 并行执行语句(Parallelize the Statement ) ORACLE 可以在SELECTs INSERTs UPDATEs MERGEs DELETEs语句中执行相应并行查询操作 对于某些DDL操作 如创建索引 用子查询创建表 在分区表上的操作 也可以执行并行操作 并行化可以导致多个服务器进程(oracle server processes)为同一个SQL语句工作 使该SQL语句可以快速完成 但是会耗费更多的资源 所以除非很有必要 否则不要使用并行查询 第 步: 执行语句(Run the Statement) 到了现在这个时候 Oracle拥有所有需要的信息与资源 因此可以真正运行SQL语句了 如果该语句为SELECT查询或INSERT语句 则不需要锁定任何行 因为没有数据需要被改变 然而 如果语句为UPDATE或DELETE语句 则该语句影响的所有行都被锁定 防止该用户提交或回滚之前 别的用户对这些数据进行修改 这保证了数据的一致性 对于某些语句 你可以指定执行的次数 这称为批处理(array processing) 指定执行N次 则绑定变量与定义变量被定义为大小为N的数组的开始位置 这种方法可以减少网络开销 也是优化的技巧之一 第 步: 取出查询的行(Fetch Rows of a Query) 在fetch阶段 行数据被取出来 每个后续的存取操作检索结果集中的下一行数据 直到最后一行被取出来 上面提到过 批量的fetch是优化的技巧之一 第 步: 关闭游标(Close the Cursor) SQL语句处理的最后一个阶段就是关闭游标 DDL语句的处理(DDL Statement Processing) DDL语句的执行不同与DML语句和查询语句的执行 这是因为DDL语句执行成功后需要对数据字典数据进行修改 对于DDL语句 语句的分析阶段实际上包括分析 查找数据字典信息和执行 事务管理语句 会话管理语句 系统管理语句只有分析与执行阶段 为了重新执行该语句 会重新分析与执行该语句 事务控制(Control of Transactions) 一般来说 只有使用ORACLE编程接口的应用设计人员才关心操作的类型 并把相关的操作组织在一起 形成一个事务 一般来说 我门必须定义事务 这样在一个逻辑单元中的所有工作可以同时被提交或回滚 保证了数据的一致性 一个事务应该由逻辑单元中的所有必须部分组成 不应该多一个 也不应该少一个 · 在事务开始和结束的这段时间内 所有被引用表中的数据都应该在一致的状态(或可以被回溯到一致的状态) · 事务应该只包含可以对数据进行一致更改(one consistent change to the data)的SQL语句 例如 在两个帐号之间的转帐(这是一个事务或逻辑工作单元) 应该包含从一个帐号中借钱(由一个SQL完成) 然后将借的钱存入另一个帐号(由另一个SQL完成) 这 个操作作为一个逻辑单元 应该同时成功或同时失败 其它不相关的操作 如向一个帐户中存钱 不应该包含在这个转帐事务中 在设计应用时 除了需要决定哪种类型的操作组成一个事务外 还需要决定使用BEGIN_DISCRETE_TRANSACTIO存储过程是否对提高小的 非分布式的事务的性能有作用 lishixinzhi/Article/program/Oracle/201311/18806