数据库索引优化 oracle

请把数据表想象成一本书, 索引就是书的目录。
这里只讨论写ORACLE SQL中优化时常遇到的索引,通常有如下几类,
1. normal 顺序的btree 索引,字段值能够为空,
2. unique 惟一的顺序索引,也就是说书的目录不能出现重复项,这样索引创建时,字段是不容许有空值的
3. 组合索引 多个字段放到一块儿创建的 normal索引,相似于书的目录是多级的
4. 函数索引
5. 位图索引 适合于某列的取值状况较少, 例如性别,只有男女两个值
更复杂的索引, 不做讨论sql

索引的优缺点:

索引的优势
检索速度快,根据目录去找本身须要的东西, 显然比整个书翻一遍(全表扫描)要快不少
索引的缺点:
1. 须要单独的存储空间去保存索引, 若是一张表建了不少索引, 那么索引的空间会更大
2. 若是一张表高并发操做主要是插入、更新。那么索引过多会致使插入更新操做性能降低。
相似书的内容总在变,目录天然也要同时跟着变化。维护目录会增长额外的消耗json

oracle 是如何经过索引找到记录的?

在书目录查找的时候, 当咱们找到须要的章节时,会记住这些章节的页码, 再翻到相应的页码去寻找咱们须要的内容。
这里有两次查找: 1. 从目录找页码 2. 根据页码在内容中查找本身须要的
oracle 也是这样, 根据索引筛选可能须要的记录 rowid(rowid 是oracle每一行记录的实际物理地址,相似页码,精确到了每一行),利用rowid 读取行记录, 逐行读取记录的时候再比较这些记录是否符合其余where条件。最后返回符合条件的行。
注意:一次不可分割的子查询中中, 不论表建了多少索引,只会使用一条索引。例如数据结构

select * from users where userid=3 and username like 'json%'。

假设userid跟username字段都创建了索引,若是同时使用两条索引,userid返回了等于3的一个rowid(这里是假设,实际状况通常不知一个,例如用户登陆记录表), username 返回json开头的5个rowid。 经过两组rowid 咱们仍是没法得知,哪些rowid同时符合两个条件。并发

如何经过索引查找的更快

oracle 有本身的分析规则,仍是上面的例子, 利用userid查找起来 更快,一方面由于它只返回了一个rowid, 后续的查找只需遍历一个结果集,判断这个结果集是否 like 'json%',另外一方面like操做更耗时。哪条索引查出来的rowid少天然就更快。
咱们能够用索引提示的方式,来指定oracle使用哪条索引,使用这样的格式 /*+index(表名或表别名 索引名)*/oracle

select /*+index(users users_idx1)*/ * from users where userid=3 and username like 'json%'

实际状况中, 可能更复杂,例如:函数

select * from users where userid=3 and login_time=to_date('yyyy-mm-dd hh24:mi:ss', '2014-02-14 03:00:00')

这里可能userid 跟 login_time 都是独立的normal索引,并且查询效率都较高,须要根据表的实际状况去选择。若是 用户量很大,查询的时间只是到天,可能使用userid字段的索引更快,若是查询的时间精确到了秒, 可能时间索引更快高并发

若是须要查看 oracle 使用了哪条索引,查看执行计划即可,在pl/sql工具中,只需按F5或explain sql工具

组合索引的状况复杂一些

相似书的目录有多级目录同样, 组合索引是创建在多个字段的, 不一样的字段顺序不一样的组合索引,相似多级目录,调换了上下级,就是新的目录。
基本上书籍都是多级目录, 通常从咱们一级目录开始查找。
组合索引也遵循这样的规则,示例以下:性能

create index user_idx1 on user_log(userid, username, log_time)
// 如下方式,查询条件中使用了组合索引第一列(前导列)均可以使用 组合索引
select * from user_log where userid=3 and  username like 'json%' and log_time=to_date('yyyy-mm-dd hh24', '2014-02-14 03');
select * from user_log where userid=3 and log_time=to_date('yyyy-mm-dd hh24', '2014-02-14 03');
select * from user_log where userid=3;
// 跳过 第一列的状况, 将再也不使用使用组合索引(oracle 9i以上版本会使用跳跃扫描)
selec * from user_log where log_time=to_date('yyyy-mm-dd hh24', '2014-02-14 03');

函数索引

查找中对字段使用函数时,将会忽略直接建立于字段上的索引。优化

select * from users where upper(username) = 'JSON'

这样的查询, 须要建立函数索引

create index users_upper_idx on users(upper(username))

理解起来也很简单, 当对字段使用了函数的时候,查询已经不是字段的值了,原来基于字段值创建的索引,天然失效。

哪些查询会没法使用索引

sql优化中要注意这些状况,调整sql以便使用索引
模糊查询在字符串开端使用通配符,会忽略索引。如 like '%json'like '%json%' 对非函数索引的字段, 使用了函数 对于index索引 不会存储 null类型,is null 是不会使用该类索引的 索引自己是利用合理的数据结构,根据值的比较,来达到快速检索的目的,以上列举的几种状况,显然都没法经过比较值来查找到最终结果

相关文章
相关标签/搜索