Oracle 性能优化建议31条

 

1.ORACLE化器共有3

     ARULE (基于规则) bCOST (基于成本) cCHOOSE (选择)

置缺省的化器,可以通过对init.ora文件中OPTIMIZER_MODE参数的各声明,如RULECOSTCHOOSEALL_ROWSFIRST_ROWS 。 你当然也在SQL或是会(session)级对行覆盖。

了使用基于成本的化器(CBO Cost-Based Optimizer) , 你必须经常运行analyze 命令,以增加数据中的统计信息(object statistics)的准确性。

如果数据化器模式为选择(CHOOSE),那么实际化器模式将和是否运行analyze命令有。 如果tableanalyze化器模式将自CBO , 反之,数据将采用RULE形式的化器。

在缺省情况下,ORACLE采用CHOOSE化器, 了避免那些不必要的全表(full table scan) ,你必尽量避免使用CHOOSE化器,而直接采用基于规则或者基于成本的化器。
2.
访问Table的方式
     ORACLE 采用两种访问表中记录的方式:

     A、 全表

          全表描就是序地访问表中记录ORACLE采用一次入多个数据(database block)的方式化全表描。

     B、 通ROWID访问

          你可以采用基于ROWID访问方式情况,提高访问表的效率, ROWID包含了表中记录的物理位置信息。ORACLE采用索引(INDEX)实现了数据和存放数据的物理位置(ROWID)系。通常索引提供了快速访问ROWID的方法,因此那些基于索引列的查询就可以得到性能上的提高。
3.
共享SQL语句
    了不重解析相同的SQL句,在第一次解析之后,ORACLESQL句存放在内存中。这块位于系全局区域SGA(system global area)的共享池(shared buffer pool)中的内存可以被所有的数据共享。 因此,当你行一个SQL(被称一个游),如果它和之前的句完全相同, ORACLE就能很快得已被解析的句以及最好的行路径。ORACLE个功能大大地提高了SQL行性能并省了内存的使用。

可惜的是ORACLE对简单的表提供高速(cache buffering)个功能并不适用于多表查询

数据管理init.ora为这个区域置合适的参数,当个内存区域越大,就可以保留更多的句,当然被共享的可能性也就越大了。

当你向ORACLE提交一个SQL句,ORACLE会首先在这块内存中找相同的句。里需要注明的是,ORACLE两者采取的是一种严格匹配,要达成共享,SQL句必完全相同(包括空格,行等)

数据管理init.ora为这个区域置合适的参数,当个内存区域越大,就可以保留更多的句,当然被共享的可能性也就越大了。

共享的句必须满足三个条件:

     A、字符的比: 当前被行的句和共享池中的句必完全相同。

     B、两个句所指的象必完全相同:

     C、两个SQL句中必使用相同的名字的(bind variables)
4.
选择最有效率的表名顺序(只在基于规则的优化器中有效)
    ORACLE的解析器按照从右到左的FROM子句中的表名,因此FROM子句中写在最后的表( driving table)将被最先理。在FROM子句中包含多个表的情况下,你必须选择记录条数最少的表作表。当ORACLE理多个表,会运用排序及合并的方式接它。首先,描第一个表(FROM子句中最后的那个表)对记录进行派序,然后描第二个表(FROM子句中最后第二个表),最后将所有从第二个表中索出的记录与第一个表中合适记录进行合并。

如果有3个以上的表查询, 那就需要选择交叉表(intersection table)表, 交叉表是指那个被其他表所引用的表。
5.WHERE子句中的连接顺序
    ORACLE采用自下而上的顺序解析WHERE子句,根据这个原理,表之间的连接必须写在其他WHERE条件之前,那些可以过滤掉最大数量记录的条件必须写在WHERE子句的末尾。
6.SELECT子句中避免使用 ' * '
    当你想在SELECT子句中列出所有的COLUMN时,使用动态SQL列引用 '*' 是一个方便的方法。不幸的是,这是一个非常低效的方法。实际上,ORACLE在解析的过程中, 会将'*' 依次转换成所有的列名, 这个工作是通过查询数据字典完成的,这意味着将耗费更多的时间。
7.减少访问数据库的次数
    当执行每条SQL语句时,ORACLE在内部执行了许多工作:解析SQL语句,估算索引的利用率,绑定变量,读数据块等等。由此可见,减少访问数据库的次数,就能实际上减少ORACLE的工作量。
8.
使用DECODE函数来减少处理时间
    使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表。
9.整合简单,无关联的数据库访问
    如果你有几个简单的数据库查询语句,你可以把它们整合到一个查询中(即使它们之间没有关系)
10.删除重复记录

11.TRUNCATE替代DELETE
     除表中的记录时,在通常情况下, 回(rollback segments ) 用来存放可以被恢的信息。 如果你没有COMMITORACLE会将数据恢除之前的状(准确地是恢除命令之前的状况)

     而当运用TRUNCATE, 回段不再存放任何可被恢的信息。当命令运行后,数据不能被恢。因此很少的源被用,时间也会很短。
12.
尽量多使用COMMIT
     只要有可能,在程序中尽量多使用COMMIT这样程序的性能得到提高,需求也会因COMMIT放的源而减少

     COMMIT放的源:

     A、回段上用于恢数据的信息。

     B、被程序得的

     C redo log buffer 中的空

     DORACLE管理上述3种资源中的内部花
13.
计算记录条数
     和一般的点相反,count(*) count(1)稍快,当然如果可以通索引索,索引列的数仍旧是最快的。例如 COUNT(EMPNO)
14.
Where子句替换HAVING子句
     避免使用HAVING子句,HAVING 只会在索出所有记录之后才对结果集过滤理需要排序,总计等操作。如果能通WHERE子句限制记录的数目,那就能减少方面的开销
15.
减少对表的查询
     在含有子查询SQL句中,要特注意减少表的查询
16.
通过内部函数提高SQL效率

17.使用表的别名(Alias)
     当在SQL句中接多个表使用表的名并把名前Column上。这样一来,就可以减少解析的时间并减少那些由Column引起的错误
18.
EXISTS替代IN
     多基于基表的查询中,足一个条件,往往需要另一个表接。在这种情况下,使用EXISTS(NOT EXISTS)通常将提高查询的效率。
19.
NOT EXISTS替代NOT IN
     在子查询中,NOT IN子句将行一个内部的排序和合并。无在哪情况下,NOT IN都是最低效的 (查询中的表行了一个全表遍)了避免使用NOT IN ,我可以把它改写成外(Outer Joins)NOT EXISTS
20.
用表连接替换EXISTS
     通常来 , 采用表接的方式比EXISTS更有效率
21.
EXISTS替换DISTINCT
     当提交一个包含一多表信息(比如部表和雇)查询时,避免在SELECT子句中使用DISTINCT。 一般可以考EXIST

22.用索引提高效率:

索引是表的一个概念部分,用来提高索数据的效率,ORACLE使用了一个复杂的自平衡B-tree. 通常,索引查询数据比全表描要快. ORACLE找出查询Update句的最佳路径, ORACLE化器将使用索引. 联结多个表使用索引也可以提高效率. 另一个使用索引的好,它提供了主(primary key)的唯一性验证.。那些LONGLONG RAW数据, 你可以索引几乎所有的列. 通常, 在大型表中使用索引特有效. 当然,你也会发现, 描小表,使用索引同能提高效率. 然使用索引能得到查询效率的提高,但是我也必注意到它的代价. 索引需要空来存,也需要定期维护, 当有记录在表中增减或索引列被修改, 索引本身也会被修改. 意味着记录INSERT , DELETE , UPDATE此多付出4 , 5 次的磁I/O . 索引需要外的存,那些不必要的索引反而会使查询应时间变.。定期的重构索引是有必要的.
ALTER INDEX <INDEXNAME> REBUILD <TABLESPACENAME>

23.sql语句用大写的

因为oracle总是先解析sql语句,把小写的字母转换成大写的再执行

24.java代码中尽量少用连接符连接字符串!

25 .>=替代>
高效: SELECT * FROM EMP WHERE DEPTNO >=4

低效: SELECT * FROM EMP WHERE DEPTNO >3

两者的区在于, 前者DBMS将直接跳到第一个DEPT等于4记录而后者将首先定位到DEPTNO=3记录并且向前描到第一个DEPT大于3记录.

26.UNION替换OR (适用于索引列)
通常情况下, UNIONWHERE子句中的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, 那就需要返回记录最少的索引列写在最前面

27.避免在索引列上使用IS NULLIS NOT NULL
避免在索引中使用任何可以空的列,ORACLE将无法使用索引.列索引,如果列包含空,索引中将不存在此记录. 合索引,如果个列都空,索引中同不存在此记录. 如果至少有一个列不空,则记录存在于索引中.: 如果唯一性索引建立在表的A列和B列上, 并且表中存在一条记录A,B值为(123,null) , ORACLE将不接受下一条具有相同A,B123,null)的记录(插入). 然而如果所有的索引列都空,ORACLE认为整个键值为空而空不等于空. 因此你可以插入1000 条具有相同键值记录,当然它都是空! 不存在于索引列中,所以WHERE子句中索引列行空将使ORACLE停用索引.
低效: (索引失效) SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL; 高效: (索引有效) SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;

28.UNION-ALL 替换UNION ( 如果有可能的话)
    SQL句需要UNION两个查询结果集合,两个果集合会以UNION-ALL的方式被合并, 然后在出最终结果前行排序. 如果用UNION ALL替代UNION, 这样排序就不是必要了. 效率就会因此得到提高. 需要注意的是,UNION ALL 将重复输出两个果集合中相同记录. 因此各位是要从业务需求分析使用UNION ALL的可行性. UNION 对结果集合排序,个操作会使用到SORT_AREA_SIZE这块内存. 这块内存的化也是相当重要的. 下面的SQL可以用来查询排序的消耗

29.需要当心的WHERE子句:
    某些SELECT 句中的WHERE子句不使用索引. 里有一些例子. 在下面的例子里, (1)‘!=' 将不使用索引. , 索引只能告你什存在于表中, 而不能告你什不存在于表中. (2) ‘||'是字符接函数. 就象其他函数那, 停用了索引. (3) ‘+'是数学函数. 就象其他数学函数那, 停用了索引. (4)相同的索引列不能互相比,将会启用全表.

30.带有DISTINCT,UNION,MINUS,INTERSECT,ORDER BYSQL语句会启动SQL引擎 执行耗费资源的排序(SORT)功能. DISTINCT需要一次排序操作, 而其他的至少需要行两次排序. 通常, UNION, MINUS , INTERSECTSQL句都可以用其他方式重写. 如果你的数据SORT_AREA_SIZE配得好, 使用UNION , MINUS, INTERSECT也是可以考, 竟它的可性很

31.优化GROUP BY:
提高GROUP BY 语句的效率, 可以通过将不需要的记录在GROUP BY 之前过滤掉.下面两个查询返回相同结果但第二个明显就快了许多。

 

你可能感兴趣的:(oracle)