Oracle会取得一行,使用一个内部函数或者你提供的每个函数对其计算散列,然后使用这个散列值得出该行数据应该在磁盘上的哪个位置。
理想情况下,散列值均匀地分布到为散列聚簇分配的所有块上,从查询利用一个I/O就能直接找到数据。
实际中,最后可能会有多行数据的散列值散列到同一个数据库块地址,而且这个块上放不下这么多行,这就会导致块串链,用一个链表把块串起来,来保存散列到这个块的所有行,当需要获取与某个散列键匹配的行时,可能必须访问多个块。
与创建索引聚簇相比,增加了3个参数:
1)HASHKEYS
此选项用来指定散列表的大小。
Oracle将HASHKEYS值“舍入”为与之最接近的质数(散列键数总是一个质数),然后再将SIZE参数乘以修改后的HASHKEYS值,根据这个结果为聚簇分配空间。也就是至少需要分配的空间字节数。
可以用公式(HASHKEYS/trunc(blocksize/SIZE))来计算散列聚簇需要预留的最少块数量。
例如,如果将SIZE设置为1,500字节,而且块大小为4KB, Oracle会在每个块上存储两个键。如果HASHKEYS设置为1000,那么Oracle至少会分配500个块。
一般地,如果刚刚创建一个空表,该表在HWM下的块数为0,如果对它执行全表扫描,达到HWM就会停止。但是对于一个散列聚簇,表一开始就很大,需要花更长的时间创建,因为Oracle必须初始化各个块(而对于一般的表,这个动作通常在数据增加到表时才发生)。散列聚簇表有可能把数据放在第一个块和最后一个块中,而中间什么都没有。对一个几乎为空的散列聚簇进行前面扫描与全面扫描一个满的散列聚簇所花的时间是一样的。
所以,建立散列聚簇的目的是为了根据散列键查找从而非常快地访问数据,而不是为了频繁地对它进行全面扫描。
2)HASH IS
此选项用来指定散列函数。可以指定一个SQL函数。如果不指定则使用Oracle内部的散列函数。
3)SINGLE TABLE
此选项用来指定创建单表散列聚簇(single table hash cluster),这是散列聚簇有一个特例。它只支持聚簇中存在一个表。
这种散列聚簇是为按主键来快速访问一个表而设计得。例如,需要按EMPNO快速地访问员工记录。
不过,使用散列算法来定位数据有一个副作用,如果不向表增加一个传统的索引,将无法对散列聚簇中的表完成区间扫描。在一个索引聚簇中,如果有以下查询:
select * from empployee where depno between 10 and 20
它就能利用聚簇键索引来找到这些行。
但是在一个散列聚簇中,这个查询会导致一个全表扫描,除非DEPNO列上已经有一个索引。
创建散列聚簇表的步骤:
1)创建散列聚簇
2)创建表格
散列聚簇适用于以下情况:
· 很清楚表中会有多少行,或者知道一个合理的上界。HASHKEY和SIZE参数的大小要正确,这对于避免聚簇重建至关重要。
· 主要执行获取操作相比,DML(特别是插入)很少。更新不会引入严重的开销, 除非更新了HASHKEY(更新HASHKEY会导致行迁移)。
· 经常按HASHKEY值访问数据。