1、如果列上有索引,但对列进行了函数运算后,查询优化器将不能使用这个索引。但11G引入虚拟列后,可以针对函数列收集统计信息,函数列索引可以被查询优化器使用;
2、如果列上有索引,但WHERE 该列 IS NULL类的查询却不能使用此索引,位图索引和复合索引除外,这两种索引允许空值的存在;
3、索引全扫描比全表扫效率低,因为索引中包含的条目更多;--主要是可避免回表操作(TABLE ACCESS BY INDEX ROWID)。另外,通过ROWID访问是最快的方式,不需要用任何索引。
4、索引是按序(升序)存储的,因此排序、求最大最小值(全索引扫描、范围扫描)的速度很快,但一个SQL里面同时求最大最小值,速度不会快;--同一个SQL中,可以这样以提高速度:select max,min from (select max(xx) max from xxx) a,(select min(xx) min from xxx) b.
5、索引跳跃扫描的效率取决于引导列唯一值的个数。因为建立复合索引时,会根据引导列唯一值的个数将索引划分为多个逻辑索引,唯一值越多,逻辑索引越多,管理起麻烦,扫描越慢。但在等值查询时,复合索引的哪一列在前,性能都一样。当一列是范围查询,一列是等值查询时,等值查询列放在前的复合索引最高效(此种情况下,范围查询比IN(X,Y)的效率更低)。过多的字段建立复合索引往往是不可取的,因为这样索引必然过大,不仅影响了定位数据,更严重影响了更新性能,一般不宜超过3个字段组合。复合索引只用于列AND的时候,OR连接的时候不会被使用。如果单列的查询列和复合索引的前置列一样,那么此单列可以不建索引,直接利用复合索引来进行数据检索。复合索引也能很有效的避免回表。一般情况下,where后面的条件如果不是复合索引的第一个键值,该复合索引将不能被使用,但是,如果复合索引中引导列的值的重复度较高(不同值较少),ORACLE会选择INDEX SKIP SCAN(ORACLE中凡事无绝对,需要根据场景来定)
6、索引快速全扫描更像全表扫描而不像其他类型的索引扫描。当选用索引快速扫描时,所有索引块将通过多块读取来进行读取。这种类型的索引扫描是用来查询列表中所有字段都包含在索引中并且索引中至少有一旬具有非空约束时替代全表扫描的。在这种情况下,数据通过索引来进行了访问而不必访问表数据块。与其他索引扫描类型的不同,索引快速全扫描并不能用来避免排序,因为数据块是通过无序的多表块读来读取的。
7、驱动表选择:当优化器可以确定其中的一张表基于UNIQUE或PRIMARY KEY约束将最多返回一行的时候,这张表在联结过程中将放在前面;使用外连接运算符的表,必须放在所联结表的后面;其他的联接顺序都是由优化器使用所能得到的表、列及索引统计信息计算得到的选择比来进行了评估的。
8、分区修剪:
可以使用分区修剪的条件
条件 RANGE LIST HASH
= √ √ √
IN √ √ √
BETWEEN,>,>=,<,<= √ √ ×
IS NULL √ √ ×
不等号(!=或<>),NOT IN 与NOT NULL条件与基于表达式和函数的限制条件不产生分区修剪
9.函数索引的扫描性能介于普通索引和全表扫之间,因为函数索引的列运算有一定的COST,优化时尽量用普通索引,避免列运算。
10.分区的TUNCATE,ADD,DROP,EXCHANGE会导致全局索引失效,需要在执行命令时添加UPDATE GLOBAL INDEXES或重建索引。如果设置了分区索引,但是却用不到分区的字段条件,性能将下降。
另一方面,如果用到了分区条件,并且有相当多的分区,此时如果使用全局索引,性能反而较低。
11.select count(*),sum(xxx),avg(xxx),在一般情况下ORACLE会使用全表扫描。这是因为,索引的列值是不能为空的,如果此时使用索引扫,ORACLE不能确定是否有空值,为了保险起见,ORACLE会选择比较稳妥的全表扫。为了使用此时能使用索引,我们需要做的是,让ORACLE知道索引列没有空值出现。比如指定索引列IS NOT NULL、非空、为主键(主键不能为空特性)等。COUNT(*)的性能,在非空列上有BTREE索引的情况下,用到此索引的性能远高于全表扫描,不过性能最高的是列上有位图索引的情况,甚至比用到普通非空列的BTREE索引时的性能又高出一截。对于sum(xxx),avg(xxx),后面加IS NOT NULL和不加是等价的,但性能明显更好。
12.索引的聚集因子,指的是有多少临近的索引条目指到不同的数据块,因子越大表示数据越无序,索引回表的开销也就越大。两张相同数据的表,并且在相同的列上有索引,执行相同的语句,聚集因子小的索引的查询的性能优于聚集因子大的。
13.索引的特性,有序性,可以利用此特性,在ORDER BY、DISTINCT列上建索引,以避免SORT,但生产环境使用DISTINCT时,一般是因为有重复的值,此时建索引意义不大。
14.一般来说,建立索引可以消除排序,但对于UNION却是个例外,因为UNION是两个结果集间的排序去重,各个表的索引已不能使用到。可以结合实例应用考虑用UNION ALL来消除UNION排序。
15.索引的危害:并不是索引越多越好,在表数据大量变动时,索引越多或越大,更新性能越差。此时,我们可以先将索引失效后,再变动(DML)数据,完成后再建索引,性能可大幅度提升。索引对DML操作的影响严重级为INSERT>DELETE>UPDATE.建索引会引起排序。这是因为建索引需要把当前索引更的列值都取出来,排序后依次插入块中形成索引块。排序是非常耗CPU的动作,如果在系统繁忙时再增加大量排序,雪上添霜。另外,建索引的过程会产生锁,而且不是行级锁,是把整个表锁住,这是为了避免任何值被改变,此时任何针对些表的DML操作都被阻止。为了加快创建索引的速度,可以适当加大PGA_AGGREGATE_TARGET。鉴于索引有危害,我们可以监控索引的使用情况,来决定是否保留此索引(没用到的索引,反而会影响数据变更效率)。具体方法为:ALTER INDEX XX monitoring usage;(关闭用nomonitoring),然后查看v$object_usage中的USED字段。在没有开启监控时v$object_usage是没有数据的。这种方法在生产环境中需谨慎使用。
16.对于where a=x and b=xx and c=xx..的查询(即席查询),在相应的列上建立位图索引(前提,此列的记录值重复度高),查询性能相当高,但如果列数据更新时,性能相当糟糕。COUNT(*)的性能,在非空列上有BTREE索引的情况下,用到此索引的性能远高于全表扫描,不过性能最高的去是列上有位图索引的情况,甚至比用到普通非空列的BTREE索引时的性能又高出一截
17.select * from t where substr(object_name,1,4)='CLUS'性能差,可等价改写为select * from t where object_name like 'CLUS%',性能明显提高。
18.优化SQL时思考列运算是否有必要,ORDER BY 是否有必要。
19.指定表的连接方式及驱动表(排序合并无驱动表被驱动表的概念)的选择: , ,数据直接追加到数据段的最后(增加新的extent),不需要花费时间在段中寻找空间,数据不经过DATA BUFFER,直接定到数据库文件中,效率要比传统的加载方式高。直接加载的数据是放在表的高水位以上的,当加载完成后,ORACLE将表的高水位线移到新加入的数据之后,这样新的数据就可以被用户使用了(详见“直接加载”部分)。SQL*LODER也属于直接加载。这些操作都不经过SGA,并且要先获得对象的TM锁,create as也需要TM锁。
29.只读表空间在RAC中是十分有用的,在CACHE FUSHION下,如果某个表空间是只读的,那么这个表空间中数据的访问只需要本地操作就行了,不需要RAC间的协同,这样就可以减少GES和GCS对系统的性能影响。
30.对于对象上的等待事件,可以从v$segment_statistics上入手。
31.对于LMODE=4的TX锁,可能是ITL等待或都等待索引节点分裂。
32.对于同字段的条件,用in比or更高效。
33.对于ROWNUM=0(<1) 目的是为了获取一个空数据集,却导致了全表扫描,对于大表,会产生大量的逻辑物理读,造成没必要的性能消耗,对于这类语句,应统一替换为WHERE 1=0 假 条件处理