首页 > 数据库 > Oracle > 索引@oracel索引技术之索引优化
下面情况即使表中存在索引,优化器也会倾向于选择全表扫描
1 被访问的表很小 有少数几个块组成
2 需要从表中获取大量的数据
3 where 子句引用索引列上只存在极少数不同值
4 表上定义了较高并行度
索引扫描:
索引唯一扫描 查询只从表中获取单个行 在主键约束索引列上指定相等条件时也会使用索引唯一扫描 在指定某个唯一索引的所有列时候也会使用
索引范围扫描 访问具有高度选择性的数据时 按升序返回索引列的值 如果所有索引列都是相同的 按照rowid的顺序输出
索引跳跃式扫描 一个查询未在where子句中指定复合索引的前导列
全索引扫描 给定索引列中所有条目的操作 是全表扫描 然后排序的很好替代方式 select * from a order by id;
索引快速全扫描 当索引本身包含查询中指定的所有列时 select b,e from test where e>1000; 使用多块读来读取索引
---查询索引是否有被使用
alter index employees_idx1 monitoring usage;--打开索引监控
select index_name,monitoring,used from v$object_usage;--查询使用情况
---可以查看数据库访问某个索引的次数
select * from dba_hist_sql_plan;
select * from dba_hist_sqlstat;
/*+no_index(表名,索引名)*/ 索引
/*+no_indext_ffs(表名,索引名)*/ 索引快速扫描
/*+no_indext_ss(表名,索引名)*/ 跳跃式索引扫描
/*+full(表名)*/ 强制表扫描
1000w行数据 表使用10w 个表块存储 索引块有2w个大约 索引高度为3 BLEVEL为2 每个索引列有100个不同的值 这些值是均匀分布的 所以该索引的每个索引值将出现1000w/100
select * from a where id='abcde';
首先读取根和分支块
然后读取索引页块的1% 相当于20000*1%
因为请求了表中所有列,所以接下来数据库必须读取表中所有行,此时关键变量就是表中的聚簇因子 假设每个数据块选择1%,总成本便是0.01*10000000
此时若是选择全表扫描 multi_loock_read_count的值设置为10的话,一共会有10000000/10次访问,可以看出比走索引更快
dba_tab_cols中的unm_distince列可以想哈看任意列中不同数值的数量
列的选择性*页块 来估算访问索引期间 数据库必须读取多少个数据块
选择性:列值有多少个不同的值 。如果索引是非常有选择性的 那么每个索引条目只有很少几行。
dba_indexs中的clustering_factor列可以找到聚簇因子的值:用来衡量表中数据的有序程度 如果聚簇因子很接近行数,那么数据便会很随机的排列 (并不能保证数据排列的随机性)
---表的选择性*聚簇因子=通过索引访问表的成本
良好的聚簇因子接近表的块数 而糟糕的聚簇因子接近表的行数
使用通配符的查询,优化器可能会选择忽略索引,而使用全表扫描,如果匹配模式中的前导字符不是%或则—— ,可能会使用索引。
在谓词中引用空值:此时为了确保数据库会使用索引的唯一方法便是保证此表两列中至少有一列被定义为not null,如果某列的索引列都是空,oracle数据库就不会把该行包括到索引中。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/30018455/viewspace-1428315/ ,如需转载,请注明出处,否则将追究法律责任。