cmu 15445 课程笔记:哈希表

476 阅读3分钟

数据库中使用到哈希表的结构:

internal meta-data:内部元数据

core data storage:核心数据集结构存储

temporary data structures:临时数据

table indexes:表的索引

HASH TABLES

design decisions

考虑两个方面:哈希表的数据结构,并发问题;

哈希表本质是一个表,一列是key,一列是value,类似于map,但是map的key不重复,哈希表的key可能会重复

哈希表的特点:

空间复杂度:O(n),占的空间和其存储的数据是线性相关的

时间复杂度:平均:O(1);最差:O(n),最差的时候是key的值全部重复,只能存在一个桶里

static hash table

静态哈希表。

image.png

对于静态哈希表:我们假设每个键都是独一无二的,不同的key对应的桶不冲突。(这是不可能的)

设计哈希表

hash 函数

如何将大范围的key映射到哈希表小范围的桶里;速度和碰撞率?

哈希schema

如何处理碰撞;是直接分配一个大的哈希表还是通过额外的措施(动态调整大小)来解决key的冲突?

哈希函数

any input key => return an integer

整数可以代表这个key

哈希表使用的不是一个加密(数据加密完之后,无法获得数据原先的任何一种情况)的哈希函数,该加密过程比较复杂(相对于mod函数之类)

哈希函数的要求就是:快,同时碰撞少;

常用哈希函数

CRC-64、MurmurHash、Google CityHash、Facebook XXhash、Google FarmHash

哈希函数的性能对比:

image.png

随着key的长度的改变,吞吐量的改变

静态哈希schemes

线性探测哈希(开放寻址哈希)

插入时:如果出现碰撞,则开始向下一个地址寻找,存放到下一个空的位置

image.png

image.png

删除时:对碰撞的处理,

C与A碰撞,删除C后,此时查D会出问题:

image.png

解决方法:

Tombstone(墓碑),设定此处为原本有数据,但已删除。

Movement:整理后续的冲突数据,里面有很多问题需要处理

image.png

非唯一键(NON-Unique Keys)

即一个key对应多个value。

可以使用链表存储,key指向一个链表,该链表存储了所有的value

或者,使用key|value作为key

Robin hood hashing

基础数据结构:开放寻址哈希。但,除了键值外,还需要记录[0],表示数据被推了多少格的位置。

image.png

image.png

如果此时hash(E) = hash(A),如果把E插入,此时会占D的位置;

image.png

cuckoo hashing

(杜鹃鸟)

多个哈希表。碰撞时,找其他的哈希表的存储,如果备用哈希表仍然冲突,先去最初的hash table,再去其他备用hash表来。

image.png

observation

之前方法的缺点:空间始终是有限的,对于静态的哈希表而言。无法动态伸缩

三种动态的哈希表:chained hashing、extendible hashing、linear Hashing

chained hashing

拉链式哈希表

引入桶的概念

image.png

image.png

extendible hashing

只看key的二进制位的前两位,

image.png

image.png

桶满怎么处理:把看key的位数增大,去看hash值的前三位,将桶的个数也增加,但是需要将现有桶内存的数据要再重新整理一下

image.png

Linear hashing

桶满怎么处理:overflow桶

image.png 当前槽溢出,从0号槽开始分加槽,此时分加的槽,使用第二个哈希函数。再发现有槽有溢出时,再将1号槽分加。直到所有槽都会进行分加,接下来如果还增加,那再从0号槽开始分加。 例如:当检测到,指向0号槽的数据,再计算一次第二个哈希函数的结果,再来说最终放到哪个槽里。

image.png

总结

哈希表对于查询而言,支持O(1)的查找时间复杂度。哈希表在DBMS中有很多地方的应用。

哈希表在速度和灵活性(空间伸缩)之间平衡

哈希表通常不用于表的索引(哈希表对于范围查询无用)