索引

1.是什么?为什么?

索引的主要目的是提高系统的性能,加快数据的查询速度与减少系统的响应时间

2.分类

索引有两种类型,聚集索引(clustered index)和非聚集索引(unclustered index)

2.1 聚集索引

2.1.1 定义:数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同。一个表中只能拥有一个聚集索引

2.1.2 适用情况:

        经常对某些列进行范围搜索,例如查询一段日期范围。当找到包含的第一个数据的行之后,便可以确保后续索引值的行在物理位置上相邻。

        经常对查出的数据按照某一列进行排序,也可以在该列上建立聚集索引,避免在每次查询数据时都进行排序,从而节约时间成本。

        当索引值唯一时,使用聚集索引查找特定的也很有效率,例如建立主键

        

动作描述

使用聚集索引 

 使用非聚集索引

 外键列

 应

 应

 主键列

 应

 应

 列经常被分组排序(order by)

 应

 应

 返回某范围内的数据

 应

 不应

 小数目的不同值

 应

 不应

 大数目的不同值

 不应

 应

 频繁更新的列

不应 

 应

 频繁修改索引列

 不应

 应

 一个或极少不同值

 不应

 不应

3.建立索引的原则

1) 定义主键的数据列一定要建立索引。

2) 定义有外键的数据列一定要建立索引。

3) 对于经常查询的数据列最好建立索引。

4) 对于需要在指定范围内的快速或频繁查询的数据列;

5) 经常用在WHERE子句中的数据列。

6) 经常出现在关键字order by、group by、distinct后面的字段,建立索引。如果建立的是复合索引,索引的字段顺序要和这些关键字后面的字段顺序一致,否则索引不会被使用。

7) 对于那些查询中很少涉及的列,重复值比较多的列不要建立索引。

8) 对于定义为text、image和bit的数据类型的列不要建立索引。

9) 对于经常存取的列避免建立索引 

9) 限制表上的索引数目。对一个存在大量更新操作的表,所建索引的数目一般不要超过3个,最多不要超过5个。索引虽说提高了访问速度,但太多索引会影响数据的更新操作。

10) 对复合索引,按照字段在查询条件中出现的频度建立索引。在复合索引中,记录首先按照第一个字段排序。对于在第一个字段上取值相同的记录,系统再按照第二个字段的取值排序,以此类推。因此只有复合索引的第一个字段出现在查询条件中,该索引才可能被使用,因此将应用频度高的字段,放置在复合索引的前面,会使系统最大可能地使用此索引,发挥索引的作用。

 

4.创建、删除索引

创建聚集索引:

create clustered index INX_INDEX on TeacheInfo(Tno,Tname,Tsex,Tage) 

创建非聚集索引:

create nonclustered index INX_INDEX on TeacheInfo(Tno,Tname,Tsex,Tage)

删除索引:

if exists(select * from sysindexes where name=索引名)
drop index 索引名
go

 

4.总结

   使用聚集索引的查询效率要比非聚集索引的效率要高,但是如果需要频繁去改变聚集索引的值,写入性能并不高,因为需要移动对应数据的物理位置。

   非聚集索引在查询的时候可以的话就避免二次查询,这样性能会大幅提升。

   不是所有的表都适合建立索引,只有数据量大表才适合建立索引,且建立在选择性高的列上面性能会更好。

 

5.索引不起作用的情况

 1.隐式转换导致索引失效.这一点应当引起重视.也是开发中经常会犯的错误.
 由于表的字段tu_mdn定义为varchar2(20),但在查询时把该字段作为number类型以where条件传给Oracle,这样会导致索引失效.
 错误的例子:select * from test where tu_mdn=13333333333;
 正确的例子:select * from test where tu_mdn='13333333333';
 2. 对索引列进行运算导致索引失效,我所指的对索引列进行运算包括(+,-,*,/,! 等)
 错误的例子:select * from test where id-1=9;
 正确的例子:select * from test where id=10;
 3. 使用Oracle内部函数导致索引失效.对于这样情况应当创建基于函数的索引.
 错误的例子:select * from test where round(id)=10; 说明,此时id的索引已经不起作用了
 正确的例子:首先建立函数索引,create index test_id_fbi_idx on test(round(id));然后 select * from test where round(id)=10; 这时函数索引起作用了
 4. 以下使用会使索引失效,应避免使用;
 a. 使用 <> 、not in 、not exist、!=
 b. like "%_" 百分号在前(可采用在建立索引时用reverse(columnName)这种方法处理)
 c. 单独引用复合索引里非第一位置的索引列.应总是使用索引的第一个列,如果索引是建立在多个列上, 只有在它的第一个列被where子句引用时,优化器才会选择使用该索引。
 d. 字符型字段为数字时在where条件里不添加引号.
 e. 当变量采用的是times变量,而表的字段采用的是date变量时.或相反情况。
 5. 不要将空的变量值直接与比较运算符(符号)比较。
 如果变量可能为空,应使用 IS NULL 或 IS NOT NULL 进行比较,或者使用 ISNULL 函数。
 6. 不要在 SQL 代码中使用双引号。
 因为字符常量使用单引号。如果没有必要限定对象名称,可以使用(非 ANSI SQL 标准)括号将名称括起来。
 7. 将索引所在表空间和数据所在表空间分别设于不同的磁盘chunk上,有助于提高索引查询的效率。
 8. Oracle默认使用的基于代价的SQL优化器(CBO)非常依赖于统计信息,一旦统计信息不正常,会导致数据库查询时不使用索引或使用错误的索引。
 一般来说,Oracle的自动任务里面会包含更新统计信息的语句,但如果表数据发生了比较大的变化(超过20%),可以考虑立即手动更新统计信息,例如:analyze table abc compute statistics,但注意,更新   统计信息比较耗费系统资源,建议在系统空闲时执行。
 9. Oracle在进行一次查询时,一般对一个表只会使用一个索引.
 因此,有时候过多的索引可能导致Oracle使用错误的索引,降低查询效率。例如某表有索引1(Policyno)和索引2(classcode),如果查询条件为policyno = xx’ and classcode = xx’,则系统有可能会使用索   引2,相较于使用索引1,查询效率明显降低。
 10. 优先且尽可能使用分区索引。

 

posted @ 2019-07-10 22:42  delay2015  阅读(105)  评论(0)    收藏  举报