Oracle SQL性能优化
1、选择合适的Oracle优化器Oracle在执行一个SQL之前,首先要分析一下语句的执行计划,然后再按执行计划去执行。分析语句的执行计划的工作是由优化器(Optimizer)来完成的。不同的情况,一条SQL可能有多种执行计划,但在某一时点,一定只有一种执行计划是最优的,花费时间是最少的。 通过PL/SQL Developer、Toad等工具可以方便的查看一个SQL语句的执行计划。 在Load中,使用快捷键Ctrl+E,查看执行计划。也可以在sqlplus中通过命令查看: SQL> explain plan for select * from emp; 已解释。 SQL> select * from table(dbms_xplan.display); PLAN_TABLE_OUTPUT -------------------------------------------------------------------------------- Plan hash value: 3956160932 -------------------------------------------------------------------------- | Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | -------------------------------------------------------------------------- | 0 | SELECT STATEMENT | | 14 | 532 | 3 (0)| 00:00:01 | | 1 | TABLE ACCESS FULL| EMP | 14 | 532 | 3 (0)| 00:00:01 | -------------------------------------------------------------------------- 已选择8行。 注:ID: 一个序号,但不是执行的先后顺序。执行的先后根据缩进来判断。 Operation: 当前操作的内容。 Rows: 当前操作的Cardinality,Oracle估计当前操作的返回结果集。 Cost(CPU):Oracle 计算出来的一个数值(代价),用于说明SQL执行的代价。 Time:Oracle 估计当前操作的时间。 (1).RBO方式 即基于规则的优化方式(Rule-Based Optimization,简称为RBO)。优化器在分析SQL语句时,所遵循的是Oracle内部预定的一些规则。比如我们常见的,当一个where子句中的一列有索 (2).CBO方式 基于代价的优化方式(Cost-Based Optimization,简称为CBO)。顾名思义,它是看语句的代价(Cost)了,这里的代价主要指Cpu和内存。优化器在判断是否用这种方式时,主要参照的是表及索引的统计信息。统计信息给出表的大小、有少行、每行的长度等信息。这些统计信息起初在库内是没有的,是你在做analyze后才出现的,很多的时侯过期统计信息会令优化器做出一个错误的执行计划,因些我们应及时更新这些信息。在Oracle8及以后的版本,Oracle列推荐用CBO的方式。 我们要明了,不一定走索引就是优的,比如一个表只有两行数据,一次IO就可以完成全表的检索,而此时走索引时则需要两次IO,这时对这个表做全表扫描(full table scan)是最好的。 (3).CHOOSE方式 设置缺省的Oracle优化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各种声明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你当然也在SQL句级或是会话(session)级对其进行覆盖。 如果数据库的优化器模式设置为选择性(CHOOSE),那么实际的Oracle优化器模式将和是否运行过analyze命令有关。如果table已经被analyze过, 优化器模式将自动成为CBO , 反之,数据库将采用RULE形式的优化器。
2、选择最有效率的表名顺序ORACLE的解析器按照从右到左的顺序处理FROM子句中的表名,因此FROM子句中写在最后的表(基础表 driving table)将被最先处理 。当ORACLE处理多个表时,会运用排序及合并的方式连接它们。首先,扫描第一个表(FROM子句中最后的那个表)并对记录进行派序,然后扫描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中检索出的记录与第一个表中合适记录进行合并。只在基于规则的优化器中有效。 例如: 表 TAB1 100000 条记录 选择TAB2作为基础表 (最好的方法) 如果有3个以上的表连接查询,那就需要选择交叉表(intersection table)作为基础表,交叉表是指那个被其他表所引用的表。 例如:
SELECT * FROM LOCATION L,CATEGORY C,EMP E WHERE E.EMP_NO BETWEEN 1000 AND 2000 AND E.CAT_NO = C.CAT_NO AND E.LOCN = L.LOCN; 将比下列SQL更有效率 SELECT * FROM EMP E,LOCATION L,CATEGORY C WHERE E.CAT_NO = C.CAT_NO AND E.LOCN = L.LOCN AND E.EMP_NO BETWEEN 1000 AND 2000; 3、Where子句中的连接顺序 Oracle采用自下而上的顺序解析WHERE子句。根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。 例如: (低效,执行时间156.3秒) SELECT * FROM EMP E WHERE SAL > 50000 AND JOB = ‘MANAGER’ AND 25 < (SELECT COUNT(*) FROM EMP WHERE MGR = E.EMPNO); <p>(高效,执行时间10.6秒)</p><p> SELECT *</p><p> FROM EMP E</p><p> WHERE 25 <(SELECT COUNT(*) FROM EMP</p><p> WHERE MGR=E.EMPNO)</p><p> AND SAL > 50000</p><p> AND JOB = ‘MANAGER’;</p> 4、SELECT子句中避免使用“*”
5、减少访问数据库的次数 当执行每条SQL语句时,ORACLE在内部执行了许多工作:
由此可见, 减少访问数据库的次数,就能实际上减少ORACLE的工作量。 如果有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系),以减少多于的数据库IO开销。虽然采取这种方法,效率得到提高,但是程序的可读性大大降低,所以还是要权衡之间的利弊 。 6、使用Truncate而非Delete
陆续更新中…… (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- New in the Flash Player 11 (Incubator) API
- iOS Google跟踪代码管理器集成:如何在每个应用环境中添加多
- ruby-on-rails – Rails – 使用外部SOAP API的最佳方式?
- Oracle Sql Developer输出格式
- 【转】内核移植之vivi分区问题
- 如何读写XML文档节点值?
- [cocos2dx_Lua]quick中的节点帧事件
- react-native —— 在Mac上搭建React Native Android开发环
- ruby – 在Windows上的每个请求中重新加载Sinatra应用程序
- 具有条件lookbehind和捕获组的.net正则表达式