Oracle基于函数的索引

  • 基于函数的索引
    比如执行如下一条SQL语句:select * from emp where upper(ename) = ‘KING’,即使在ename上建立了索引,还是会全表扫描emp表,将里面的ename字段改成大写跟常量KING进行比较。如果我们建立一个基于函数的索引,比如:create index emp_upper_idx on emp(upper(ename)); 这个时候,我们只需要按区间扫描小部分数据,然后获取rowid取访问表中的数据,这个速度是比较快的。
    基于函数的索引,类似于普通的索引,只是普通的索引是建立在列上,而它是建立在函数上。当然这回对插入数据有一定影响,因为需要通过函数计算一下,然后生成索引。但是插入数据一般都是少量插入,而查询数据一般数据量比较大。为了优化查询速度,稍微降低点插入速度是可以承担的。
    函数索引还有一个功能,只对部分行建立索引。假设有一个很大的表,有一列叫做FLAG,只可能取Y和N。假设大部分数据是Y,小部分数据是N,我们需要将N修改成Y。如果建立一个普通索引,这个索引会非常大,而且将N修改成Y的时候,维护这个索引开销会很大。不过这个表听起来比较适合位图索引,但这是一个事物系统(OLTP),可能有很多人同时插入记录,或者进行修改。那么位图索引也不适合。所以,如果我们只是在值为N的行上建立索引,就比较好办了。
    只在值为N的行建立索引SQL:create index flag_index on big_table(case flag when ‘N’ then ‘N’ end);这样一个索引大小会大大降低,而且维护成本也会很低的。前提是我们只对值为N的行感兴趣。

  • 位图索引
    位图索引的适用条件
    位图索引适合只有几个固定值的列,如性别、婚姻状况、行政区等等,而身份证号这种类型不适合用位图索引。
    位图索引适合静态数据,而不适合索引频繁更新的列。

举个例子,有这样一个字段busy,记录各个机器的繁忙与否,当机器忙碌时,busy为1,当机器不忙碌时,busy为0。

这个时候有人会说使用位图索引,因为busy只有两个值。好, 我们使用位图索引索引busy字段!假设用户A使用update更新某个机器的busy值,比如update table set table.busy=1 where rowid=100;,但还没有commit,而用户B也使用update更新另一个机器的busy值,update table set table.busy=1 where rowid=12; 这个时候用户B怎么也更新不了,需要等待用户A commit。

原因:用户A更新了某个机器的busy值为1,会导致所有busy为1的机器的位图向量发生改变,因此数据库会将busy=1的所有行锁定,只有commit之后才解锁。

问题: 为什么更新了某个机器的busy值为1,会导致所有busy为1的机器的位图向量发生改变,因此数据库会将busy=1的所有行锁定?

答案请看位图索引的存储结构。

位图的存储,位图中位的个数和表中的记录数项目,

比如下面婚姻状况表
姓名(Name) 性别(Gender) 婚姻状况(Marital)
张三 男 已婚
李四 女 已婚
王五 男 未婚
赵六 女 离婚
孙七 女 未婚

表中有5行记录,所以创建的记录会有5位
性别列-男的位图: 10100
性别列-女的位图: 01011
已婚列的位图: 11000
未婚列的位图: 11000
离婚列的位图: 11000
所以现在知道了吧, 当要更新位图索引时,就要更新这个位图,那么将会锁定整个位图或者要更新的这个位所在的块。

发布了70 篇原创文章 · 获赞 20 · 访问量 9万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章