每日一文
►索引:
索引是表的一个概念部分,用来提高检索数据的效率。通常,通过索引查询数据比全表扫描要快。虽然使用索引能得到查询效率的提高,但是我们也必须注意到它的代价。
索引需要空间来存储,也需要定期维护,每当有记录在表中增减或索引列被修改时, 索引本身也会被修改。这样每条记录的增删改将多执行4 , 5 次的磁盘读写操作。因为索引需要额外的存储空间和处理,那些不必要的索引反而会使查询反应时间变慢,所以索引不能盲目的建立。
►索引并不一定会提高查询效率
1)如果检索数据量超过30%的表中记录数,使用索引将没有显着的效率提高。
2)在特定情况下,使用索引也许会比全表扫描慢,但这是同一个数量级上的差距;而通常情况下,使用索引比全表扫描要快几倍乃至几千倍。
►建立索引遵循的原则
1)表的主键、外键必须有索引;
2)经常与其他表进行连接的表,在连接字段上应该建立索引,多表进行多字段连接,建议适当建立复合索引;
3)索引应该建立在查询条件中进行比较的字段上,而不是建立在我们要找出来并且显示的字段上;
4)在条件表达式中经常用到的不同值较多的列上建立检索,在不同值少的列上不要建立索引;比如“性别”列上只有“男”与“女”两个值,不适合建立索引。如果建立索引不但不会提高查询效率,反而会严重降低更新速度。组合索引要尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。
►造成索引失效的几种情况
1)IN、OR子句常会使索引失效。如果不产生大量重复值,可以考虑把子句拆开。拆开的子句中应该包含索引。以下sql不会用到索引:
select * from test whereaaa="111" or bbb="222";
2)IS NULL 或IS NOT NULL会限制索引的使用。因为NULL值并没有被索引定义。在SQL语句中使用NULL会有很多的麻烦。因此建议开发人员在建表时,把需要索引的列设成NOT NULL。如果被索引的列在某些行中存在NULL值,就不会使用这个索引。也可以使用特定的值来代替NULL(比如0为空值,1为非空)。
请避免在索引中使用任何可以为空的列,oracle将无法使用该索引。
对于单列索引,如果列包含空值,索引中将不存在此记录;对于复合索引,如果每个列都为空,索引中同样不存在此记录。如果至少有一个列不为空,则记录存在于索引中
因为空值不存在于索引列中,所以where子句中对索引列进行空值比较将使数据库停用该索引
索引失效举例:
select* fromtable1 where dept_code is not null
3)条件字段使用函数和表达式。如果不使用基于函数的索引,那么在SQL语句的WHERE子句中对存在索引的列使用函数时,会使优化器忽略掉这些索引。
下面的查询不会使用索引:
select* fromempwheretrunc(hiredate)<"-05-30";
改为下面语句会使用索引:
select* from emp wherehiredate<to_date("-05-30");
请务必注意,检索中不要对索引列进行处理,如:trim,to_date,类型转换等操作,破坏索引,使用全表扫描,影响sql执行效率。
4)避免在索引列上使用计算。如果索引列是函数的一部分,优化器将不使用索引而使用全表扫描。
不使用索引:
select* fromdept where sal*12>25000;
使用索引:
select* fromdept where sal>25000/12;
5)警惕隐性转换数据类型。比较不匹配的数据类型也是比较难于发现的性能问题之一。比如:account_number是一个VARCHAR2类型,在account_number字段上有索引。
下面的语句将执行全表扫描:
select* from bankswhereaccount_number=12345;
12345是数字类型,而account_number是字符类型,进行了隐性转换,从而不适用索引。
to_number(account_number)=990354
解决办法:在12345上加单引号
6)带通配符(%)的like语句。要求在职工表中查询名字中包含wang的人。可以采用如下的查询SQL语句:
select * fromemployee where name like "%wang%";
这里由于通配符(%)在搜寻词首出现,所以Oracle系统不使用name的索引。在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度。然而当通配符出现在字符串其他位置(比如关键词后面)时,优化器就能利用索引。
在下面的查询中索引得到了使用:
select * fromemployee where namelike "wang%";
7)order by语句。order by语句决定了数据库如何将返回的查询结果排序。任何在Order by语句的非索引项或者有计算表达式都将降低查询速度。仔细检查order by语句以找出非索引项或者表达式,它们会降低性能。解决这个问题的办法就是重写order by语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在order by子句中使用表达式。
8)>或<,大于或小于操作符。大于或小于操作符一般情况下是不用调整的,因为它有索引就会采用索引查找,但有的情况下可以对它进行优化。
使用">="代替">",使用"<="代替"<"
如一个表有100万记录,一个数值型字段A,30万记录的A=0,30万记录的A=1,40万记录的A=2,2万记录的A=3。那么执行A>2与A>=3的效果就有很大的区别了,因为A>2时数据库会先找出为2的记录索引再进行比较,而A>=3时数据库则直接找到=3的记录索引。