SQL语句优化原则

数据库性能是整个应用程序性能的重要部分。数据库优化涉及的内容非常广泛,各类数据库都提供众多的性能指标和大量的优化工 具。

下面我们简单介绍一下优化的基本概念。
一个运行良好的数据库至少应具有以下特点:

合理的物理结构及硬件能力
合理的物理结构指数据库文件及整个网络的物理分布。硬件能力指是否有足够的硬件资源来完成应用程序功能。合理的物理结构至少带来两个方面的好处:

1、                适量的数据冗余,提高数据安全性。

2、                平衡磁盘IO,增强数据读写能力。

而足够的硬件能力的作用自然不言而喻。一旦建立好数据库系统并开始运行,数据库的物理结构就不能改变。

合理的系统参数
对应数据库来说,随着数据量的变化,数据库性能也一直处在变化之中,因此数据库建立之初设定的系统参数会变的越来越不合适,有时甚至阻碍了数据库的正常运 行,导致性能瓶颈。因此观察性能变化,随时调整系统参数,使数据库一直处于一个良好的运行状态,就成为管理员最重要的日常工作之一。对系统参数的合理调 整,常常能将数据库从崩溃的边缘挽救回来。oracle、sqlserver这样的高品质数据库都为系统参数提供了灵活多变的调整方式。一般来说,只要数 据库结构设计不存在重大缺陷,通过后期的调整,都可以使数据库运行在一个良好的状态下。

性能优良的sql语句
sql语句是在程序开发阶段就已经决定了的,由低效率的sql语句给数据库性能带来的问题,往往在数据库开始运行一段时间后才凸现出来(随着数据量的不断 增加),但发现后就变的难以改变,成为不可突破的性能瓶颈。因此,作为一名合格的开发人员,应该建立基本的优化概念和良好的编程习惯,从整体上提高应用程 序的质量。

同时,提高sql语句的执行效率,是提高整个数据库性能的最立竿见影且价格低廉的方法之一。因为几乎所有的数据库都会不可避免的运行一些效率低下的 sql语句。对数据库性能的调整,往往都是从sql语句调优开始的。

下面我们简单介绍数据库是怎么执行sql语句的。

sql语句是唯一从应用程序发送到数据库实例的命令。数据库实例所做的全部工作就是接受、解释和执行sql 语句。

在绝大多数情况下,我们并不需要关心sql语句是怎么执行的,这是因为在当前流行的数据库软件中都无一例外的采用了高性能的优化器,而这些优化器在 绝大多数的情况下都能将用户某些不合理的sql语句结构转换成更合理的形式,从而有效提高sql的执行效率。

优化器的优化原理有两种:

基于成本的优化
对一条sql语句,优化器会生成所有可能的执行方式,估计这些执行方式将使用的硬件成本,相互比较后从中选择成本最低的执行计划。缺点是必须收集大量统计 数据,对服务器造成额外的负担。

基于规则的优化
相对基于成本的优化,基于规则的优化则显得死板的多。比如sqlserver遇到blog_id=*的情况就会去找索引,实在找不到索引才使用全表扫描。 而不考虑有时候不用索引可能效率更高。显然有些情况下基于规则的优化并不合适。

/*执行计划的概念:简单的说执行计划就是指在执行sql语句前对代码进行编译时数据库实例为sql选择的执行路径。如一个sql对A、B、C三个 表进行联合查询,数据库会首先以某种方式对这3个表种符合条件的记录进行查询(全表扫描或其他),再将A、B、C表中符合条件的记录读入内存,将A、B表 的记录相比较后得出的结果集与C表相比较,最后得到符合的结果集。但实际情况比这复杂的多。*/

oracle可以选择两种优化模式之中的一种,而其他数据库则是固定的(DB2不清楚,关于DB2的资料太少了),基本都是基于规则的优化。

然而优化器毕竟不是智能的。很多时候,它不可避免的受到sql语句结构的影响。而SQL优化的实质就是在结果正确的前提下,用优化器可以识别的语 句,充份利用索引,减少表扫描的I/O次数,尽量避免表扫描的发生。

sql的书写原则

以下介绍的标准sql的书写原则是本文的核心,这些原则适用于绝大部分数据库。介绍这些原则的时候,我会举一些简单的例子来说明,但这些例子在实际 生产中可能没有什么实际意义。

1、使用索引
如果没有任何索引,在执行sql语句时必定将做全表扫描。这和我们在看一本书时,如果没有目录,我们只能从第一页开始查找,直到找到查询的内容是一个道 理。全表扫描是效率最低的查询方式,我们会看到绝大多数的低效率sql就是使用的全表扫描。因此在对一些大表进行查询的时候,我们需要关心一下表中是否建 立了索引并尽量使用索引。

总的来说索引可以分为聚集索引和非聚集索引。一个表中只能有一个聚集索引。对一个表建立一个聚集索引后,数据库会调整表记录的顺序,使表按照索引的 顺序重新排列。而非聚集索引则不会改变表的结构。

使用的最常见的索引就是主键索引。实际上在表中指定一列为主键的时候,就在这列上建立了唯一值索引并强制该列的值唯一,这就成了主键索引。

在下面几种情况下,应该建立索引:

1.   有大量重复值、且经常有范围查询(between,>,<,>=,<=)和order by、group by发生的列,可以考虑使用聚集索引;

2.   在使用最频繁的列且常常需要使用函数的时候,可以考虑使用函数索引。

3.   在使用最频繁的列且常常需要对两个或多个列进行联合查询的时候,可以考虑使用组合索引。

4.   在重复率较低的列上建立唯一索引。

索引虽有助于提高性能,但不是索引越多越好,恰好相反过多的索引会导致系统低效。因为用户在表中每加进一个索引,维护索引集合就要做相应的更新工 作,同时每次有数据改变的时候就需要维护索引。

因此尽管使用索引非常有必要,但是在以下情况下,我们并不赞成使用索引。

1、  大量对表数据的修改(插入过删除)

2、  数据量很小

关于怎么使用索引,就是多使用存在索引的列作为查询条件。但是使用了带索引的列,也不一定就使用了索引,后面会提到相应的知识。

2、和任何高级语言一样,sql也是越简单越好。
大家先看看下面的语句:

Select TOP $size$ BLOG_ID AS blogID,

BLOG_DOMINO AS blogDomino,

BLOG_TEMPLATE_ID AS blogTemplateID

FROM blog

Where BLOG_ID NOT IN

(Select BLOG_ID

from blog

where BLOG_ID>=$size$+$fromID$)

AND LOCKED=1

orDER BY BLOG_ID DESC;

通过查看执行计划,我们可以看到执行查询的步骤:

1、子查询中使用blog.pk_blog(主键索引)查询BLOG中满足blog>=$size$+$fromID$的记录,这步占总成本 的46%。

2、使用blog.pk_blog(主键索引),查询BLOG中满足LOCKED=1的记录。这步占总成本的44%。

3、使用Merge join。这步占总成本的10%。总成本为0.23。

我们可以看到两次对blog表的查询都使用了blog_id上的主键索引,同时表连接消耗的资源也比较少。应该说,对于子查询结构,这个查询的效率 并不低。但是,这和下面的语句完全是等价的:

Select TOP $size$ BLOG_ID AS blogID,

BLOG_DOMINO AS blogDomino,

BLOG_TEMPLATE_ID AS blogTemplateID

FROM blog

Where BLOG_ID<$size$+$fromID$

AND LOCKED=1

orDER BY BLOG_ID DESC;

总成本为0.0035。

优化器不是人工智能,在第一个查询中指定使用子查询结构,优化器就无法突破这个限制,尽管两个查询是相同的,优化器还是不能将第一种查询结构等价的 转换成第二种。所以查询语句使用的结构对优化器影响重大,我们在进行多表查询等复杂情况的时候的时候(如可能需要使用联接查询、子查询、嵌套查询、 group by等),应多进行一些考虑。一个原则是结构要尽量简单,这样在编译效率、执行效率和程序可读性方面都有好处。

3、谨慎使用is null和is not null
    不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使在列上建立了索引,只要这些列中有一个含有null,该列就会从索引 中排除。也就是说,如果某列存在空值,即使对该列建索引也不会提高性能。同时,任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。

4、in和exists
很多资料都声称exists的效率高于in。而实际情况证明,在子句中使用in和exists效率是一样的。

Select ProductName

FROM Northwind.dbo.Products

Where UnitPrice in

(Select UnitPrice

FROM Northwind.dbo.Products

Where ProductName = ‘Sir Rodney’’s Scones’)

Select ProductName

FROM Northwind.dbo.Products b

Where exists

(Select UnitPrice

FROM Northwind.dbo.Products a

Where a.ProductName = ‘Sir Rodney’’s Scones’

and a.UnitPrice=b.UnitPrice)

查看执行计划可以看到,上面两个语句的执行路径和执行成本都完全一样。

5、in和or
sqlserver会自动将in转换成or,因此对sqlserver来说下面两个语句是一样的,而其他数据库中in的效率要高于or。

select blog_name

from blog

where blog_name like ‘AB%’

or blog_name like ‘CD%’

or blog_name like ‘EF%’;

select blog_name

from blog

where blog_name in (‘AB%’,’CD%’,‘EF%’);

6、查询字段要需要多少,查询多少
我们每少提取一个字段,查询速度就会有相应的上升。这主要是因为物理读取成本降低了。所以要避免select *这样的查询,需要哪些字段就查询哪些字段。

7、将行和操作数减到最少
使用 Where 和 HAVING 子句只选择需要的行,可以将 Select 语句返回的行数减到最少。尽量少用不等于运算符 <> 或 !=。数据库将必须在表或索引中扫描所有的值,以查看它们是否不等于表达式中给定的值。可以使用范围重写表达式:

Where KeyColumn < ‘TestValue’ AND KeyColumn > ‘TestValue’8、尽量少用格式转换,防止出现隐含的格式转换。
举个简单的例子:

某个表中有一个时间字段time date型,现在开发人员需要写一个sql:查询出在2004-04-21到2005-04-21之间,注册了多少blog新用户。我们比较下面两个语 句:

select *

from blog

where to_char(create_time,yyyymmdd) between ’20040421’and ’20050421’;

――将time转换成字符型,和’20040421’及’20050421’做比较。

select *

from blog

where create_time<=to_date(‘2004-04-21’,’yyyy-mm-dd’)

and create_time<=to_date(‘2005-04-21’,’yyyy-mm-dd’);

――将20040421及20050421转换成date型,和create_time做比较。

(PL/SQL)

第二个语句的性能明显优于第一个。这是因为第一个sql数据库必须将每一行记录的create_time都转换一次,而第一个只需要对常量做一次转 换。(第二个语句的性能明显优于第一个的另一个重要原因就是第一个查询不能使用create_time上的索引)。

隐含的格式转换既是数据库在必要时会自动将一个数据类型转换成另一种可兼容的数据类型:

最常见的情况,一个字段sort_id varchar(10)型,现在要查询出所有sort_id为3的用户。

Select * From blog Where sort_id=3;

如果用户没有查看表结构,很可能认为sort_id是int型而写出上面的语句。同时,数据库不会报错,这是因为编译引擎自动做了一次数据类型转 换。这就是一个隐藏转换的典型例子。在查询大量数据的时候,这样不必要的转换会降低sql的效率。

9、带通配符(%)的like语句
要求在blog表中查询名字中包含“我”的人。可以采用如下的查询SQL语句:

select * from blog where blog_name like ‘%我%’;

这里由于通配符(%)在搜寻词首出现,所以Oracle将不使用blog_name的索引。在很多情况下可能无法避免这种情况,但是一定要心中有 底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时,优化器就能利用索引。在下面的查询中索引得到了使用:

select * from blog where blog_name like ‘c%’;

对于sqlserver,这种情况没有影响。

10、ORDER BY和GROPU BY
对于ORDER BY和GROUP BY短语,任何一种索引都有助于Select的性能提高。但是使用聚集索引的效率最高。如blog表,blog_id 为主键索引,blog_name上有一个聚集索引。

Select *

From blog

order by blog_name;

由于聚集索引一个表中只能有一个,因此在无法使用聚集索引的情况下,使用其他索引也能提高查询效率。

11、禁止进行列运算
任何对列的操作都将导致表扫描,原因是对列进行运算将直接导致无法使用该列上的索引(除非建立了函数索引)。它包括数据库函数、计算表达式等等。因此,查 询时要尽可能将操作移至等号右边。

Select *

From blog

Where blog_id=3;

观察执行计划,发现使用了索引blog.PK_blog,整个查询消耗了cpu time:0.00008;I/O成本:0.0032。预计成本:0.0032。而如果改成:

Select *

From blog

Where cast(blog_id as char)=’3’;

――将blog_id转换为char型后与’3’相比较。

观察执行计划,发现使用了索引blog.IX_plogs_blog_id(这里使用这个索引的原因是由于无法使用 blog.PK_blog,sqlserver退而求其次,使用了建立在plogs_blog_id字段上的索引),整个查询消耗了cpu time:0.264;I/O成本:0.345。预计成本:0.61。性能下降了200倍!

同样,应将类似:where blog_id*1000>28847;的语句改为:where blog_id>28.847;

12、使用表提示
使用表提示的本质是影响优化器,使优化器按照指定的执行计划来执行sql语句(通常是制定多表连接时的连接方式)。一般情况下并不需要使用表提示,因为优 化器总是能选择适当的执行计划。这种做法只是增加了性能优化的可能性,并不一定会产生好的影响。

由于使用表提示有时反而会降低执行效率,因此,只有当我们发现一些sql在低效运行且认为有必要干预sql执行计划的时候(可能已经严重影响了应用 程序的运行)才使用。同时需要通过反复调试来达到最佳的效果。

使用表提示的方法:Oracle中使用hint提示,sqlserver中使用option子句。

13、慎用游标
在某些必须使用游标的场合,可考虑将符合条件的数据行转入临时表中,再对临时表定义游标进行操作,这样可使性能得到明显提高。

14、关于多表连接和子查询
在实际应用中我们常常会遇到需要使用多表连接或子查询的情况。同时我们会发现,很多时候这两种查询结构可以做等量的转换。下面的例子就是这样: select ProductNameFROM Northwind.dbo.ProductsWhere UnitPrice in(Select UnitPriceFROM Northwind.dbo.ProductsWhere ProductName = ‘Sir Rodney’’s Scones’) Select Prd1.ProductNameFROM Northwind.dbo.Products AS Prd1JOIN Northwind.dbo.Products AS Prd2  ON (Prd1.UnitPrice = Prd2.UnitPrice)Where Prd2.ProductName = ‘Sir Rodney’’s Scones’

(T-sql。使用的是northwind示例数据库中的表)

子查询和不包括子查询但语义上等效的语句在性能方面通常没有区别。但是,在一些必须检查存在性的情况中,使用联接会产生更好的性能。否则,为确保消 除重复值,必须为外部查询的每个结果都处理嵌套查询。所以在这些情况下,联接方式会产生更好的效果。如下面两个等效的sql:

Select distinct a.blog_name

From blog a

Where exists(

Select b.blog_id

From blog_note b

Where a.blog_id=b.blog_id

And b.create_time<’2005-04-25’ );

Select distinct a.blog_name

From blog a,blog_note b

Where a.blog_id=b.blog_id  

And b.create_time<’2005-04-25’;

分析结果:

查询执行计划可以看到执行成本:语句一:使用exists子查询,总成本0.0567语句二:联接查询,总成本0.0535。

15、增加执行计划的重复使用率
执行计划生成后便驻留在高速缓存中。很多时候一段sql代码并不是执行一次就完了,同样的代码会连续执行很多次。如一个用户查询了自己的用户资料,0.1 秒后另一个用户执行了相同的操作。如果数据库能识别出这两次sql语句是同样的,在第二次执行时就不会再次编译sql,而是直接使用驻留在高速缓存中的执 行计划。在某些大型系统中一些基础的sql可能会每秒执行上千次。因此重复使用执行计划可以大大缩短sql的执行时间。但是有的时候数据库不能识别出类似 的sql语句,比如用户查询自己资料的例子:

第一个用户:

select * from blog where blog_id=1;

第二个用户查询的是:

select * from blog where blog_id=455;

sql文本的变化导致数据库认为这是两个不同的查询,无法重复使用执行计划。为了提高执行计划的重复使用率,建议:

1、  使用对象(如表和视图)的完全合法名称。如:

Select * from blogctynnd.dbo.blog;

2、  oracle强烈建议在应用程序中大量使用“绑定变量”,如下:

将:select * from blog where blog_id=1;

改为:

SQL>declarevid int default 1;res varchar(4);beginexecute immediate ’select * from blog where blog_id =:x’ into res using vid;dbms_output.put_line(res);  –oracle系统包,用于输出。end;/(PL/SQL。这一招的用意很明显就是 固定sql文本,把编译器骗过去,有点瞒天过海的意思。其他数据库使用绑定变量的方法也是一样的,只是使用的语句稍有不同。)

对于sqlserver来说使用绑定变量意义不大,因为sqlserver数据库引擎可以识别出上面给出的例子,绑定变量具有一定的优势,但并不明 显。

另外需要说明的是在优化器内部对执行计划会存在一个衰减列表,到一定时间后执行计划还没有被重复使用,就会被清除出这个列表,这时再执行sql语句 就必须重新编译了。

其实SQL的性能优化是一个复杂的过程,上述这些只是在应用层次的一种体现,深入研究还会涉及数据库层的资源配置、网络层的流量控制以及操作系统层 的总体设计。另外,不同的数据库使用的优化原则不同,导致对同样的sql语句,做出完全不同的执行计划。即使是同样的数据库、同样的语句,在数据库运行的 不同时期执行效率也会发生很大的变化。因此,对数据库的优化更多的时候是对数据库的观察和调试,而不是教条式的简单修改。有兴趣的同事可以使用下面的方式 查看sql语句的执行计划,而执行计划反映了此刻sql语句的执行过程,使用的资源等等,是sql语句效率高低的量化数据。

oracle:

sql>@rdbms/admin/utlxplan.sql――运行utlxplan.sql脚本,会自动创建一个plan_table。 这步只需要做一次。建立后每次进入sqlplus时:

sql>set autotrace on

这时每次执行sql,都会显示出相应的执行计划。

Sqlserver:

在sqlserver中查看执行计划非常简单:进入查询分析器,在窗体中输入T-sql语句。点击【查询预计的执行计划】(该按钮在切换数据库下拉 菜单的左边。或ctrl+l)。这时执行计划就会显示在窗体下端。

其他数据库查看执行计划的方式如有需要可以上网查找。欢迎多交流。

后记

对于现有的每一种数据库来说,标准SQL的功能显然太弱了。因此,每一种数据库都对标准SQL进行了性能扩展。对于oracle是PL/SQL。 Sqlserver是T-sql。

在本文中列举的例子,并不一定在你的数据库中也能成功执行。同时,本文中的某些原则,可能对于特定数据库、特定优化模式下的sql性能并不能起到明 显改善的作用。

比如在使用通配符的例子中:

select * from employee where last_name like ‘%cliton%’;

对于oracle,将无法使用last_name上的索引,导致这个查询会发生全表扫描。而对于sqlserver来说,仍然可以正常使用索引。

尽管如此,在开发过程中对一些小细节的注意,不仅可以保证在大多数数据库中有较高的执行效率,还可以使sql语句在今后数据库运行的过程中或某些特 殊情况下(如系统迁移),也能长期保持稳定的状态。

转载于:https://www.cnblogs.com/Gaojier/archive/2010/04/08/2783563.html

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

(转)SQL 优化原则 一、问题的提出  在应用系统开发初期,由于开发数据库数据比较少,对于查询SQL语句,复杂视图的的编写等体会不出SQL语句各种写法的性能优劣,但是如果将应用系统提交实际应用后,随着数据库中数据的增加,系统的响应速度就成为目前系统需要解决的最主要的问题之一。系统优化中一个很重要的方面就是SQL语句优化。对于海量数据,劣质SQL语句和优质SQL语句之间的速度差别可以达到上百倍,可见对于一个系统不是简单地能实现其功能就可,而是要写出高质量的SQL语句,提高系统的可用性。   在多数情况下,Oracle使用索引来更快地遍历表,优化器主要根据定义的索引来提高性能。但是,如果在SQL语句的where子句中写的SQL代码不合理,就会造成优化器删去索引而使用全表扫描,一般就这种SQL语句就是所谓的劣质SQL语句。在编写SQL语句时我们应清楚优化器根据何种原则来删除索引,这有助于写出高性能的SQL语句。   二、SQL语句编写注意问题   下面就某些SQL语句的where子句编写中需要注意的问题作详细介绍。在这些where子句中,即使某些列存在索引,但是由于编写了劣质的SQL,系统在运行该SQL语句时也不能使用该索引,而同样使用全表扫描,这就造成了响应速度的极大降低。   1. IS NULL 与 IS NOT NULL   不能用null作索引,任何包含null值的列都将不会被包含在索引中。即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除。也就是说如果某列存在空值,即使对该列建索引也不会提高性能。   任何在where子句中使用is null或is not null的语句优化器是不允许使用索引的。   2. 联接列   对于有联接的列,即使最后的联接值为一个静态值,优化器是不会使用索引的。我们一起来看一个例子,假定有一个职工表(employee),对于一个职工的姓和名分成两列存放(FIRST_NAME和LAST_NAME),现在要查询一个叫比尔.克林顿(Bill Cliton)的职工。   下面是一个采用联接查询的SQL语句, select * from employss where first_name||''||last_name ='Beill Cliton'; 上面这条语句完全可以查询出是否有Bill Cliton这个员工,但是这里需要注意,系统优化器对基于last_name创建的索引没有使用。   当采用下面这种SQL语句的编写,Oracle系统就可以采用基于last_name创建的索引。 *** where first_name ='Beill' and last_name ='Cliton'; . 带通配符(%)的like语句   同样以上面的例子来看这种情况。目前的需求是这样的,要求在职工表中查询名字中包含cliton的人。可以采用如下的查询SQL语句: select * from employee where last_name like '%cliton%'; 这里由于通配符(%)在搜寻词首出现,所以Oracle系统不使用last_name的索引。在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置时,优化器就能利用索引。在下面的查询中索引得到了使用: select * from employee where last_name like 'c%'; 4. Order by语句   ORDER BY语句决定了Oracle如何将返回的查询结果排序。Order by语句对要排序的列没有什么特别的限制,也可以将函数加入列中(象联接或者附加等)。任何在Order by语句的非索引项或者有计算表达式都将降低查询速度。   仔细检查order by语句以找出非索引项或者表达式,它们会降低性能。解决这个问题的办法就是重写order by语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在order by子句中使用表达式。 5. NOT   我们在查询时经常在where子句使用一些逻辑表达式,如大于、小于、等于以及不等于等等,也可以使用and(与)、or(或)以及not(非)。NOT可用来对任何逻辑运算符号取反。下面是一个NOT子句的例子: ... where not (status ='VALID') 如果要使用NOT,则应在取反的短语前面加上括号,并在短语前面加上NOT运算符。NOT运算符包含在另外一个逻辑运算符中,这就是不等于(<>)运算符。换句话说,即使不在查询where子句中显式地加入NOT词,NOT仍在运算符中,见下例: ... where status <>'INVALID'; 对这个查询,可以改写为不使用NOT: select * from employee where salary<3000 or salary>3000; 虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。 虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些。第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引。 =============================================================================================== 我们要做到不但会写SQL,还要做到写出性能优良的SQL,以下为笔者学习、摘录、并汇总部分资料与大家分享! (1) 选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE 的解析器按照从右到左的顺序处理FROM子句中的表名,FROM子句中写在最后的表(基础表 driving table)将被最先处理,在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表。如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表. (2) WHERE子句中的连接顺序.: ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾. (3) SELECT子句中避免使用 ‘ * ‘: ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间 (4) 减少访问数据库的次数: ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等; (5) 在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200 (6) 使用DECODE函数来减少处理时间: 使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表. (7) 整合简单,无关联的数据库访问: 如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系) (8) 删除重复记录: 最高效的删除重复记录方法 ( 因为使用了ROWID)例子: DELETE FROM EMP E WHERE E.ROWID > (SELECT MIN(X.ROWID) FROM EMP X WHERE X.EMP_NO = E.EMP_NO); (9) 用TRUNCATE替代DELETE: 当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况) 而当运用TRUNCATE时, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短. (译者按: TRUNCATE只在删除全表适用,TRUNCATE是DDL不是DML) (10) 尽量多使用COMMIT: 只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少: COMMIT所释放的资源: a. 回滚段上用于恢复数据的信息. b. 被程序语句获得的锁 c. redo log buffer 中的空间 d. ORACLE为管理上述3种资源中的内部花费
表情包
插入表情
评论将由博主筛选后显示,对所有人可见 | 还能输入1000个字符
©️2021 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值