散列簇学习
散列簇这个东西,说实话我也不知道有什么用处,很少会用到。既然看到这里,就学习一下,貌似这个功能是用来处理表的一些索引结构的,实在是看了头大,记下来再说,以后有需要了再慢慢看吧。
一、散列簇的适用环境
散列簇是一种为非簇表提供索引或索引簇的一种方法,它将表存储到一个散列簇,可以改善数据检索的性能。对于索引表或索引簇,Oracle使用存储在单独的索引中的键值来定位表中的行。Oracle会物理地将表中的行存储到散列簇,并根据散列函数的结果来检索它们。
Oracle使用散列函数来产生散列值(基于特殊的簇键值的数字值分布)。散列簇建类似索引簇的键,可以是单个列或组合列。为了在散列簇中查找或存储行,Oracle将散列函数应用到行的簇键值。产生的散列值对应于簇中的数值块,然后Oracle根据发布的语句在这些数据块上读写。
在簇表或簇中查询存储行时,至少需要执行两个I/O(索引中以及表中的读写),而使用散列函数在散列簇中定位行时不需要I/O,所以至少需要1次I/O。
注:即使决定使用散列方法,表仍然可以在任何列(包括簇键)上具有单独的索引。
1、散列方法有用的情况
* 大多数查询是在簇键上的相等查询
SELECT ... WHERE cluster_key = ... ;
此时相等条件被散列,并且通常读一次就能找到对应散列键。对比索引表则需要先在索引中找到其键值,再从表中读行。
* 散列簇中的表的大小是基本不变的
此时可以确定簇中表的行数及其所需空间,如果散列簇中表需要比初始分配更多的空间,则性能将会降低(使用溢出数据块)。
2、散列方法无益的情况
* 表上大多数查询是在簇键值的一个范围中检索
SELECT ... WHERE cluster_key < ... ;
范围无法被散列,只能全表扫描,而索引是可以将键值排序的
* 表不是静止的,而是经常增长的
* 应用经常对表进行全表扫描,并且很少填充表
此情况下散列方法的全表扫描需要更长时间
* 无法提供散列簇最终需要的与分配空间
二、创建散列簇
CREATE CLUSTER trial_cluster (trialno NUMBER(5,0))
PTCUSED 80
PCTFREE 5
TABLESPACE users
STORAGE (INITIAL 250K NEXT 50K
MINEXTENTS 1 MAXEXTENTS 3
PCTINCREASE 0)
HASH IS trialno HASHKEYS 150;
CREATE TABLE trial (
trialno NUMBER(5,0) PRIMARY KEY,
...)
CLUSTER trial_cluster (trialno);
说明:
1.HASHKEY值指定和限制该簇所使用的散列函数可以产生的唯一的散列值数量(Oracle会取最接近的素数)
2.如果没有HASH IS子句,Oracle就会使用内部散列函数。
3.在散列簇上不能创建索引,也不需要在散列簇键上创建索引
1、创建单个表散列簇
单个表散列簇提供了对表中的行的快速访问。必须在散列键和数据行之间存在一对一的映射。
CREATE CLUSTER peanut (variety NUMBER)
SIZE 512 SINGLE TABLE HASHKEY 500;
注:SINGLE TABLE 选项仅对散列簇有效,且必须指定HASHKEYS
2、控制散列簇的空间使用
① 选择键
选择正确的簇键取决于针对簇表所发布的最常用的查询类型(看最常用那个键来选择行)。
最典型的簇键就是包含表的整个主键。
② 设置HASH IS
仅当簇键是NUMBER数据类型、包含均匀分布的整数的单个列时,才指定HASH IS参数。
③ 设置SIZE
应将SIZE设置成为保持任何给定散列键的所有行所需的空间的平均数
* 若散列簇仅包含单个表,且表中行的散列键值唯一,则SIZE为簇中平均的行大小
* 若散列簇包含多个表,则设置SIZE为:为保持与代表性的散列值相关的所有行所需的空间平均数
* 若散列簇不使用内部散列函数,且期望很少或没有冲突,则使用SIZE初始值
* 若预料到插入时经常冲突,则为了存储行而分配溢出数据块的高可用性,按需要适当增加SIZE
④ 设置HASHKEYS
为散列簇中行的最大分布,且Oracle会自动舍入到最近素数
3、控制散列簇的空间举例
假设数据块大小为2K,平均每个数据块可用数据空间为1950B
例1:
现打算将emp表装载进一个散列簇,大多数查询按职员号码检索职员记录,你估计,在任何给定时间中emp表最大的行数是10000,且平均行大小是55字节。
此时应将empno作为簇键,因为该列包含唯一整数,所以可不使用内部散列函数。SIZE可被设置成平均行大小(55字节)。注意,给每个数据块赋予了34个散列键。HASHKEYS可被设置成表中的行数(10000)。Oracle自动转换为最接近的素数(10007)。
CREATE CLUSTER emp_cluster (empno NUMBER)
...
SIZE 55
HASH IS empno HASHKEYS 10000;
例2:
按部门号码进行检索行,其他条件类似。且每个部门平均10个职员,部门号码按10递增(0,10,20,30,...)
此时应将deptno作为簇键,又因为该列包含均匀分布整数,所以可以不使用内部散列函数。SIZE的初始值是55字节*10,因此每个数据块被赋予3个散列键。如果预料到某些冲突,且希望数据检索的性能最好,可稍微更改所估计的SIZE值,以预防需要溢出数据块而带来冲突,调整12%的SIZE到620字节
HASHKEYS可以被设置成唯一的部门号码的个数(1000),Oracle自动转换为最接近的素数(1009)。
CREATE CLUSTER emp_cluster (deptno NUMBER
)
...
SIZE 620
HASH IS deptno HASHKEYS 1000;
4、估计散列簇所需的空间大小
依据SIZE和HASHKEYS的设置值,Oracle保证最初分配的空间足够存储散列表。如果对INITIAL、NEXT、MINEXTENTS的设置值不能满足簇的大小,则分配增加的盘区直到至少满足 SIZE*HASHKEYS
例如:假设数据块大小为2K,每个数据块可用数据空间大约为1900字节,且CREATE CLUSTER语句中指定如下:
STORAGE (INITIAL 100K
NEXT 150K
MINEXTENTS 1
PCTINCREASE 0)
SIZE 1500
HASHKEYS 100
则以上例子中每个数据块仅可赋予一个散列键,因此散列簇所需的初始空间至少是100*2K,所以设置的存储参数无法满足需求。因此需要分配给该散列簇一个100K的出示盘曲和一个150K的第2盘区。
如果HASH参数指定为:
SIZE 500 HASHKEYS 100
则此时可以给每个数据块赋予3个散列键,此时需要的初始化空间是34*2K,可以满足需求。
三、更改散列簇
ALTER CLUSTER emp_dept ...;
--与簇相同
四、删除散列簇
DROP CLUSTER emp_dept;
--与簇相同
五、散列簇相关信息
DBA|ALL|USER_CLUSTERS:该视图包含了散列簇
DBA|USER_CLU_COLUMNS:该视图包含了散列簇
DBA|ALL|USER_CLUSTER_HASH_EXPRESSIONS:列出用于散列簇的散列函数