`

高性能编程之高效SQL(2)

阅读更多

4. 常用优化方法

 

4.1 选择最有效率的表名顺序(只在基于规则的优化器中有效)

ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理. FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作为基础表..

ORACLE处理多个表时, 会运用排序及合并的方式连接它们.首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并。

如果有3个以上的表连接查询, 那就需要选择交叉表(intersection table)作为基础表, 交叉表是指那个被其他表所引用的表.

 

4.2 WHERE子句中的连接顺序.

     ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前, 那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾.

 

4.3 SELECT子句中避免使用 *

当你想在SELECT子句中列出所有的COLUMN,使用动态SQL列引用*是一个方便的方法.不幸的是,这是一个非常低效的方法. 实际上,ORACLE在解析的过程中, 会将’*依次转换成所有的列名, 这个工作是通过查询数据字典完成的, 这意味着将耗费更多的时间.

4.4 减少访问数据库的次数

ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等。

 

4.5 Where子句替换HAVING子句

避免使用HAVING子句, HAVING 只会在检索出所有记录之后才对结果集进行过滤. 这个处理需要排序,总计等操作.

假如能通过WHERE子句限制记录的数目,那就能减少这方面的开销. (oracle)onwherehaving这三个都可以加条件的子句中,on是最先执行,where次之,having最后,因为on是先把不符合条件的记录过滤后才进行统计,它就可以减少中间运算要处理的数据,按理说应该速度是最快的,where也应该比having快点的,因为它过滤数据后才进行sum,在两个表联接时才用on的,所以在一个表的时候,就剩下wherehaving比较了。

在这单表查询统计的情况下,假如要过滤的条件没有涉及到要计算字段,那它们的结果是一样的,只是where可以使用rushmore技术,而having就不能,在速度上后者要慢假如要涉及到计算的字段,就表示在没计算之前,这个字段的值是不确定的,根据上篇写的工作流程,where的作用时间是在计算之前就完成的,而having就是在计算后才起作用的,所以在这种情况下,两者的结果会不同。在多表联接查询时,onwhere更早起作用。系统首先根据各个表之间的联接条件,把多个表合成一个临时表后,再由where进行过滤,然后再计算,计算完后再由having进行过滤。由此可见,要想过滤条件起到正确的作用,首先要明白这个条件应该在什么时候起作用,然后再决定放在那里

4.6 减少对表的查询

在含有子查询的SQL语句中,要非凡注重减少对表的查询.例子:
SELECT TAB_NAME FROM TABLES WHERE (TAB_NAME,DB_VER) = ( SELECT
TAB_NAME,DB_VER FROM TAB_COLUMNS WHERE VERSION = 604)

4.7 使用表的别名(Alias)

    当在SQL语句中连接多个表时, 请使用表的别名并把别名前缀于每个Column.这样一来,就可以减少解析的时间并减少那些由Column歧义引起的语法错误.

4.8 尽量多使用COMMIT

    只要有可能,在程序中尽量多使用COMMIT, 这样程序的性能得到提高,需求也会因为COMMIT所释放的资源而减少:

 COMMIT所释放的资源:

a.       回滚段上用于恢复数据的信息.

b.       被程序语句获得的锁

c.       redo log buffer 中的空间

d.       ORACLE为管理上述3种资源中的内部花费

  说明:在使用COMMIT时必须要注意到事务的完整性,现实中效率和事务完整性往往是鱼和熊掌不可得兼

 

4.9 EXISTS替代IN

在许多基于基础表的查询中,为了满足一个条件,往往需要对另一个表进行联接.在这种情况下, 使用EXISTS(NOT EXISTS)通常将提高查询的效率.

 

4.10 NOT EXISTS替代NOT IN

在子查询中,NOT IN子句将执行一个内部的排序和合并. 无论在哪种情况下,NOT IN都是最低效的 (因为它对子查询中的表执行了一个全表遍历).  为了避免使用NOT IN ,我们可以把它改写成外连接(Outer Joins)NOT EXISTS.

 

4.11 EXISTS替换DISTINCT

当提交一个包含一对多表信息(比如部门表和雇员表)的查询时,避免在SELECT子句中使用DISTINCT. 一般可以考虑用EXIST替换。

 

4.12 用索引提高效率

索引是表的一个概念部分,用来提高检索数据的效率. 实际上,ORACLE使用了一个复杂的自平衡B-tree结构. 通常,通过索引查询数据比全表扫描要快. ORACLE找出执行查询和Update语句的最佳路径时, ORACLE优化器将使用索引. 同样在联结多个表时使用索引也可以提高效率. 另一个使用索引的好处是,它提供了主键(primary key)的唯一性验证.

除了那些LONGLONG RAW数据类型, 你可以索引几乎所有的列. 通常, 在大型表中使用索引特别有效. 当然,你也会发现, 在扫描小表时,使用索引同样能提高效率.

虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价. 索引需要空间来存储,也需要定期维护, 每当有记录在表中增减或索引列被修改时, 索引本身也会被修改. 这意味着每条记录的INSERT , DELETE , UPDATE将为此多付出4 , 5 次的磁盘I/O . 因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢.

 

4.13 基础表的选择

基础表(Driving Table)是指被最先访问的表(通常以全表扫描的方式被访问). 根据优化器的不同, SQL语句中基础表的选择是不一样的.

如果你使用的是CBO (COST BASED OPTIMIZER),优化器会检查SQL语句中的每个表的物理大小,索引的状态,然后选用花费最低的执行路径.

如果你用RBO (RULE BASED OPTIMIZER) , 并且所有的连接条件都有索引对应, 在这种情况下, 基础表就是FROM 子句中列在最后的那个表.

 

4.14避免在索引列上使用计算.

 

4.15 避免在索引列上使用IS NULLIS NOT NULL

避免在索引中使用任何可以为空的列,ORACLE将无法使用该索引.对于单列索引,如果列包含空值,索引中将不存在此记录. 对于复合索引,如果每个列都为空,索引中同样不存在此记录. 如果至少有一个列不为空,则记录存在于索引中.

举例:

  如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录的A,B值为(123,null) , ORACLE将不接受下一条具有相同A,B值(123,null)的记录(插入). 然而如果所有的索引列都为空,ORACLE将认为整个键值为空而空不等于空. 因此你可以插入1000条具有相同键值的记录,当然它们都是空!

      因为空值不存在于索引列中,所以WHERE子句中对索引列进行空值比较将使ORACLE停用该索引.

 

4.16总是使用索引的第一个列

如果索引是建立在多个列上, 只有在它的第一个列(leading column)where子句引用时,优化器才会选择使用该索引.

 

4.17UNION-ALL 替换UNION ( 如果有可能的话)

SQL语句需要UNION两个查询结果集合时,这两个结果集合会以UNION-ALL的方式被合并, 然后在输出最终结果前进行排序.

如果用UNION ALL替代UNION, 这样排序就不是必要了. 效率就会因此得到提高.

 

4.18避免使用耗费资源的操作

带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BYSQL语句会启动SQL引擎执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要执行两次排序.

例如,一个UNION查询,其中每个查询都带有GROUP BY子句, GROUP BY会触发嵌入排序(NESTED SORT) ; 这样, 每个查询需要执行一次排序, 然后在执行UNION, 又一个唯一排序(SORT UNIQUE)操作被执行而且它只能在前面的嵌入排序结束后才能开始执行. 嵌入的排序的深度会大大影响查询的效率.

通常, 带有UNION, MINUS , INTERSECTSQL语句都可以用其他方式重写

 

4.19 Java代码中尽量少用连接符连接字符串!

 

4.20 避免在索引列上使用NOT

要避免在索引列上使用NOT, NOT会产生在和在索引列上使用函数相同的影响. ORACLE”碰到”NOT,他就会停止使用索引转而执行全表扫描.

4.21 >=替代>
   
高效:
SELECT * FROM EMP WHERE DEPTNO >=4
低效:
SELECT * FROM EMP WHERE DEPTNO >3
两者的区别在于, 前者DBMS将直接跳到第一个DEPT等于4的记录而后者将首先定位到DEPTNO=3的记录并且向前扫描到第一个DEPT大于3的记录.

5.慎用优化方法

5.1 删除重复记录

最高效的删除重复记录方法 ( 因为使用了ROWID)

DELETE FROM EMP E

WHERE E.ROWID > (SELECT MIN(X.ROWID)

                   FROM EMP X

                   WHERE X.EMP_NO = E.EMP_NO);

5.2TRUNCATE替代DELETE

当删除表中的记录时,在通常情况下, 回滚段(rollback segments ) 用来存放可以被恢复的信息. 如果你没有COMMIT事务,ORACLE会将数据恢复到删除之前的状态(准确地说是恢复到执行删除命令之前的状况)

而当运用TRUNCATE, 回滚段不再存放任何可被恢复的信息.当命令运行后,数据不能被恢复.因此很少的资源被调用,执行时间也会很短

    说明:TRUNCATE只在删除全表适用,TRUNCATEDDL不是DML 

分享到:
评论

相关推荐

    SQL_Server高级编程管理指南.rar

    这本书旨在帮助读者掌握SQL Server的高级编程技巧和管理方法,以优化数据库性能、提高数据安全性和实现高效的数据存储与检索。 1. **SQL Server架构与组件** SQL Server由多个组件构成,包括数据库引擎、Analysis ...

    SQL Server高级查询与T-SQL编程知识点汇总

    学习SQL Server高级查询与T-SQL编程,意味着深入理解数据库设计原理,掌握高效的数据操作和查询技巧,这在开发和管理大型数据库系统时至关重要。通过实践和熟悉这些概念,可以提高数据库性能,确保数据的准确性和...

    Python高性能编程_python进阶_python高性能_源码.zip

    在"Python高性能编程"这个主题中,我们关注的是如何利用Python的特性来实现高效的代码执行,优化算法,以及如何处理大数据量的情况。这通常涉及到对Python语言深入理解、内存管理、并发编程、数据结构优化等多个方面...

    oracle sql 高级编程

    Oracle数据库是世界上最广泛使用的数据库系统之一,它提供了强大的功能和高效的性能,使得SQL在Oracle环境下的应用变得更为复杂和多样化。本节将详细探讨Oracle SQL的高级特性、优化技巧以及最佳实践。 一、子查询...

    Python高性能编程技术

    《Python高性能编程技术》这本书是Python开发者提升技能的宝贵资源,它深入探讨了如何利用Python的强大功能实现高效、优化的代码执行。以下是一些关键的知识点: 1. **Python解释器与性能**: Python是一种解释型...

    《Linux高性能服务器编程》(游双)

    本书旨在深入探讨如何利用Linux系统实现高性能的服务器应用,覆盖了网络协议、服务器编程的核心技术和工具框架等多个关键领域,对于想要在Linux环境下构建高效稳定服务的开发者来说,是一本不可或缺的参考书。...

    Oracle+SQL高级编程

    2. **SQL查询优化**:在Oracle中,编写高效的SQL语句是提高数据库性能的关键。这涉及到选择合适的索引、避免全表扫描、利用连接优化、使用子查询优化以及理解执行计划等技术。 3. **PL/SQL编程**:Oracle的PL/SQL是...

    SQL.Server.2005高性能编程

    《SQL Server 2005 高性能编程》是一本全面介绍如何在 SQL Server 2005 上构建高度可用和高效系统的重要参考书籍。它不仅涵盖了理论知识,还提供了实用的技术细节和最佳实践建议,对于希望深入了解 SQL Server 2005 ...

    Linux高性能服务器编程源码,linux高性能服务器编程pdf,C/C++

    在Linux平台上进行高性能服务器编程是IT领域中的一个重要课题,它涉及到网络编程、多线程、内存管理、I/O模型优化等多个方面。C/C++作为底层系统编程的主要语言,提供了高效且灵活的编程能力,使得开发者能够更深入...

    Oracle SQL 高级编程 附源码

    Oracle SQL是数据库管理员和开发人员在管理Oracle数据库时...总之,"Oracle SQL 高级编程"涵盖了数据库管理和开发的多个方面,通过学习和实践,你将能够编写出更高效、更灵活的SQL查询,更好地管理和维护Oracle数据库。

    oraclesql高级编程 随书脚本

    《Oracle SQL 高级编程》一书的随书脚本集合是学习和深入理解Oracle数据库管理及SQL高级特性的宝贵资源。这些脚本涵盖了从基础查询到复杂的数据操作、存储过程、函数以及触发器等多个方面,旨在帮助读者提升在Oracle...

    SQLServer2000高级编程技术.pdf.rar

    《SQLServer2000高级编程技术》这本书深入探讨了SQL Server 2000这一经典数据库管理系统中的高级编程技术。SQL Server 2000是微软公司推出的数据库平台,虽然现在已经有一些老旧,但其在许多企业中仍然占据着重要的...

    高级SQL数据库编程手册高级SQL数据库编程手册

    本书涵盖了SQL的高级概念和技术,帮助读者深入理解如何利用SQL进行复杂的数据操作、优化查询性能以及设计高效的数据存储方案。 SQL(Structured Query Language,结构化查询语言)是用于管理关系型数据库的标准语言...

    Oracle SQL高级编程 中文版

    它全面覆盖了Oracle SQL的各种高级特性,提供了独到的见解和详实的实例,旨在帮助读者在实际工作中更加高效地管理和优化数据库。 1. **子查询**:Oracle SQL中的子查询是SQL查询语句中嵌套的另一个查询,用于在主...

    [Oracle.SQL高级编程].Karen.Morton等.扫描版

    Oracle SQL高级编程通常指的是使用SQL语言实现复杂的数据操作、查询优化、性能调整和事务管理等方面的高级技术。 以下是Oracle SQL高级编程中的一些重要知识点: 1. 数据操纵语言(DML):在Oracle SQL中,可以...

    SQL Server2000设计与T-SQL编程

    《SQL Server 2000设计与T-SQL编程》这本书是针对数据库管理和开发人员的一份宝贵资源,尤其对于那些正在学习或...通过学习本书,你将具备设计高效数据库、编写高性能T-SQL代码的能力,为你的职业生涯增添宝贵的技能。

    SQL高级编程

    1. **数据库设计**:良好的数据库设计是高效SQL编程的前提。这包括对实体关系模型(ER模型)的理解,使用范式理论(如第一范式、第二范式、第三范式等)来减少数据冗余,以及如何创建和管理表、索引、主键和外键。 ...

    sql数据库下编程

    在IT行业中,数据库编程是至关重要的技能之一,尤其是在C++这样的强类型系统语言与SQL Server 2005这样的关系型数据库管理系统结合时。本文将深入探讨如何在C++环境中利用SQL Server 2005进行数据库操作。 首先,...

    Sqlserver数据库高级编程教程

    在SQL Server数据库高级编程中,我们经常会涉及到三个关键概念:触发器、存储过程和自定义函数。这些元素是数据库系统中的重要组成部分,用于实现复杂的业务逻辑和数据管理。以下是对这三个概念的详细解释: 1. **...

Global site tag (gtag.js) - Google Analytics