摘要:请把数据表想象成一本书,索引就是书的目录。那么索引过多会导致插入更新操作性能下降。哪些查询会无法使用索引优化中要注意这些情况,调整以便使用索引模糊查询在字符串开端使用通配符,会忽略索引。
请把数据表想象成一本书, 索引就是书的目录。
这里只讨论写ORACLE SQL中优化时常遇到的索引,一般有以下几类,
1. normal 顺序的btree 索引,字段值可以为空,
2. unique 唯一的顺序索引,也就是说书的目录不能出现重复项,这样索引建立时,字段是不允许有空值的
3. 组合索引 多个字段放到一起建立的 normal索引,类似于书的目录是多级的
4. 函数索引
5. 位图索引 适合于某列的取值情况较少, 例如性别,只有男女两个值
更复杂的索引, 不作讨论
索引的优点
检索速度快,根据目录去找自己需要的东西, 显然比整个书翻一遍(全表扫描)要快很多
索引的缺点:
1. 需要多带带的存储空间去保存索引, 如果一张表建了很多索引, 那么索引的空间会更大
2. 如果一张表高并发操作主要是插入、更新。那么索引过多会导致插入更新操作性能下降。
类似书的内容总在变,目录自然也要同时跟着变化。维护目录会增加额外的消耗
在书目录查找的时候, 当我们找到需要的章节时,会记住这些章节的页码, 再翻到相应的页码去寻找我们需要的内容。
这里有两次查找: 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(表名或表别名 索引名)*/
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 是不会使用该类索引的
索引本身是利用合理的数据结构,根据值的比较,来达到快速检索的目的,以上列举的几种情况,显然都无法通过比较值来查找到最终结果
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/17431.html
阅读 2263·2023-04-25 16:42
阅读 1163·2021-11-22 14:45
阅读 2314·2021-10-19 13:10
阅读 2806·2021-09-29 09:34
阅读 3375·2021-09-23 11:21
阅读 2071·2021-08-12 13:25
阅读 2151·2021-07-30 15:15
阅读 3471·2019-08-30 15:54