Hash table属于如图层次中的Access Methods一层,是一种用来对数据库进行读或写的方式。
数据库内部锁维护的数据结构有两种:hash table和order-preserving tree。
Page table或page directory本质上就是hash table,通过page_id得到buffer pool中的frame或者得到磁盘上的位置。
Hash Tables
哈希表是一个抽象数据类型,通过它来提供无需的关联函数实现API。
也就是将任意的key映射到对应的值上。
空间复杂度:O(n)
时间复杂度:
Avg O(1)
Worst O(n)(哈希碰撞,使得所有key都撞在一起了)
在表中保存为指针,指向key所在的位置。
下图为perfect hash funtion,也就是任意两个Key经过Hash之后的结果都不会相等的理想情况
k e y 1 ! = k e y 2 − > h a s h ( k e y 1 ) ! = h a s h ( k e y 2 ) key1 != key2 -> hash(key1) != hash(key2) key1!=key2−>hash(key1)!=hash(key2)
组成
①hash funtion,将key映射到int(确切的说,一个smaller domain)上的hash值
②hash scheme,当hash碰撞的时候的一种机制。
常见哈希函数
其中速度和碰撞率最优秀的是xxhash,设计的时候用就行了(不要自己造不好用的轮子…)。
static hash schemes
以下都是静态的也就是static hashing scheme,
在分配内存的时候就知道希望保存的key的数量,是一种离线算法。
- Linear Probe hashing
- robin hood hashing
- cuckoo hashing
Linear probe hashing
一个大型的slot表,用Hash函数跳转到表上的某些offset值上或添加slot。
添加:如果key经过hash跳转到的位置已经有元素了,那么往下扫描,直到找到空的slot可以映射key为止。
删除:移除一个Key的时候在对应slot处添加一个tombstone表示这里没有一个logic entry,这样别的元素进行查找的时候就可以向下找。
non-unique keys
- 散列表。hash之后指向一个链表,该联表上存储的value对应的hash之后的值都是一样的。
- 冗余key(redundant keys)。在slot数组中不断的复制这个key,然后利用linear probe hashing处理。
robin hood hashing
思路:让’poor key’从’rich key’中偷取slot,让每个key尽可能接近Hash到的位置,达到整体平衡。
- number of positions 表示你所在的位置与你第一次hash所计算出的距离差
cuckoo hashing
多个hash table,去决定往哪个hash table里加入key。
假设表1,表2对应hash1,hash2函数。
对一个key进行两次hash,并尽量去找有空余slot的表加入。
如果两边的slot都被占了,则先占据其中一个table假如table2。被从table2里赶出来的keyB进行hash1,然后去占有另一张表的slot,table1里的A被赶了出来。这个时候A再进行hash2,找到一个位置,然后放到table2中。(类似匈牙利算法)
要分辨出起点,若发现成环了,就要进行扩容。
dynamic hash schema
- chained hashing
- extendible hashing
- linear hashing
chained hashing(hashmap)
将所有具有hash key的元素放到一个桶里。
extendible hashing
chained hashing的桶有可能无线增长下去,因此优化就是只对overflowed的chain进行拆分,而不是将整个hash table进行拆分。
可以理解为每个bucket chain代表一个page,左侧的slot array代表的是page id,因此我们不允许多个slot指向同一个bucket chain
global参数的是我们需要看hash之后的序列的前几位,local参数是局部的bucket需要看hash序列的前几位。
左边的数组存放的是Page id,或者是指针。在扩容的之后只需要更改指针方向或page id即可。
如果page满了,则修改参数进行扩容
参考博客
问题:每次扩容都将slot array扩充两倍,且在扩充过程中要在slot array上加锁保证不会有别的线程访问导致故障,会造成性能瓶颈。
linear hashing
思想:发生溢出的时候,只重分配split pointer的bucket,不管他有没有溢出。
数学:num % n = x,num % 2*n = x + n或x。