“线性哈希选择另一条增长路线:用一个分裂指针代替这份幂二目录,但允许溢出链等待轮到自身被拆。两者都必须面对哈希偏斜,不能把某个小输入的均匀结果当成最坏性能保证。”
形式陈述
同一阶段有些桶已拆,有些还没拆
哈希表需要把键映到候选桶并处理碰撞;线性哈希让主桶数一次只增加1。采用外存页模型,每个主桶页最多放C条定长记录,额外记录串入该主桶专属的溢出页,每溢出页容量同为C。单线程完成更新,无并发、事务版本和崩溃;精确同键put覆盖,只有不同键插入才增加记录数。
设初始主桶数
若
一次增长只拆指针指向的桶
每次增长选中的都是桶s,未必是刚发生溢出的桶。处理过程如下:
- 新建主桶
- 读取桶s的整个主桶与溢出链,按模2N把记录分到s或
,重新装入各自分页链 - 令
;若变成N,则本阶段全部拆完,令 ,新阶段基数为2N
哈希恒等式
收缩是一次分裂的逆操作
删除记录本身不强制收缩。若另有策略要求收缩且主桶数大于初始
合并可能重新形成溢出链,并不要求所有记录塞回一个主桶页。释放的是最后主桶的身份与相应整理后的空页,不能把仍有记录的溢出页直接丢掉。增长和收缩阈值应分开,避免少量插删反复触发同一拆合;本页只规定一次结构变换,不给工作负载无关的自动最优阈值。
直觉
用顺序分裂省下一张大目录
可扩展哈希让哪个桶拥挤就拆哪个桶,因此要用目录记住各块已经看到了几位。线性哈希按0、1、2……的固定顺序拆,一个指针就能记住进度。
省下目录的代价是:发生溢出的桶可能暂时轮不到。新记录先留在它的溢出链里,系统去拆别的桶;以后轮到它时,再把整个链重新分配。因此“执行了一次分裂”和“这次碰撞马上消失”没有必然等号。
例子与边界
同一组键,溢出桶和被拆桶并不同
取
| 新插入 | 寻址后的目标 | 是否进入溢出部分 | 本次拆桶 | 更新后N、s | 关键内容 |
|---|---|---|---|---|---|
| 5 | 1 | 否 | — | 2、0 | 桶1=[5] |
| 9 | 1 | 否 | — | 2、0 | 桶1=[5,9] |
| 1 | 1 | 是 | 0 | 2、1 | 0拆成0/2,均空;桶1仍[5,9,1] |
| 3 | 1 | 是 | 1 | 4、0 | 模4重分:桶1=[5,9,1],桶3=[3] |
| 7 | 3 | 否 | — | 4、0 | 桶3=[3,7] |
| 13 | 1 | 是 | 0 | 4、1 | 0拆成0/4,均空;桶1=[5,9,1,13] |
最终有5个主桶0至4。桶1主页面[5,9],溢出页[1,13];桶3一页[3,7];其余主桶为空。记录总数6,实际数据页是5个主桶加1个溢出页,共6页。不能只按“6条/每页2条=3页”忽略空主桶与哈希分布。
查询13时,先
下次拆到热点,也未必消灭全部溢出
继续插17,先进入桶1的溢出部分,触发拆s=1。按模8重分整条链:9、1、17进入桶1;5、13进入新桶5。更新为N=4、s=2。原溢出记录13这次终于搬到自己的新主桶,桶1却仍有3条,依然需要一个溢出页。
如果只重分桶1主页[5,9]而忘掉链中的1、13、17,查询会依据新地址去桶5找13,却找不到。扩展寻址规则时,必须一起处理原桶承担的全部记录,而不是只处理第一页。
撤回一次增长不等于删除记录
在六键终态N=4、s=1,执行一次受控收缩会把最后桶4合回0,回到N=4、s=0,字典不变。再收缩一次,就逆转上一阶段最后拆桶1的动作:基数退为2,s设为1,把桶3合入桶1,留下0、1、2三个主桶。桶1此时有全部六个奇数键,需要3页;查找正确,但长链成本变大。
这种结构收缩可以在没有删除任何记录时执行,只是通常不利于性能。自动策略必须看自己的容量、负载或延迟目标,不能把“逆操作存在”当成“此时应该执行”。
推论与应用
两级取模为什么总指向已存在桶
设
分裂桶s只改变基础余数等于s的键,并使新地址
小元数据不等于最坏常数访问
N与s可以放在常驻元数据中,寻址至多两次取模;但找到主桶后仍须比较键并遍历溢出页。若某桶共有q条记录,紧凑分页链最多需
一次分裂重分的是桶s的q条记录,读取原链、写两个新链,记录处理为
主桶编号仍需映射到实际文件页或缓冲页;“没有哈希目录”只指不保存逐哈希前缀的
选结构时先看查询任务
这两种动态哈希都适合按完整键等值定位,哈希桶编号没有键序含义。按键范围输出仍可复用B+树的有序叶链;也不能把本页按固定次序拆桶的“线性”,误读为开放定址的线性探测。
参考资料
[1] Witold Litwin,Linear Hashing: A New Tool for File and Table Addressing,VLDB 1980,pp.212–223,§2.1在pp.213–215定义分裂函数、固定分裂顺序及寻址;§2.2在pp.215–216讨论物理页地址;§2.3.1在p.216讨论触发策略与逆向合并。链接为原刊扫描副本,本文整数例及容量账为自编。
[2] Andy Pavlo,CMU 15-445/645 Fall 2025,Lecture 07: Hash Tables,§5.3,p.4:分裂指针与已拆桶的第二次哈希。本文明确一次触发与溢出分页,避免把策略差异省成同一条轨迹。