结构图
hash 表包含了多个 segment 切片,每个 segment 包含了相同数量的 bucket。里面的 bucket 使用链表存储着 hash 值相同的元素。

当查找指定的 key 时,首先计算出它的哈希值,然后根据后面的几位数,计算出对应的 bucket 位置。之后遍历 bucket 的元素链表,查看是否有 key 元素。
当增加元素时,同样先找到对应 bucket 位置,然后查看是否存在对应的链表中。如果不存在,直接添加到尾部。如果存在则可以覆盖或者报错。
当删除元素时,同样先找到对应 bucket 位置,然后查看是否存在对应的链表中。如果存在,则只需要将其从链表中删除即可。
扩容原理
postgresql 只会在负载率过高的情况下,发生扩容操作。并且它的一次扩容只会增加一个 bucket。我们来举个例子,查看下它的扩容过程。我们先初始化只有2个 bucket 的哈希表,

计算 key 对应的 bucket 位置,需要涉及到 hign_mask 和 low_mask。下面程序实现了
/* Convert a hash value to a bucket number */
static inline uint32 calc_bucket(HASHHDR *hctl, uint32 hash_val)
{
uint32 bucket = hash_val & hctl->high_mask;
if (bucket > hctl->max_bucket)
bucket = bucket & hctl->low_mask;
return bucket;
}
当发生扩容时,会计算新增bucket的元素和原先哪个bucket有关系,需要将旧有的bucket数据重新分开。并且还会更新相关属性
new_bucket = hctl->max_bucket + 1;
// 更新最大bucket索引
hctl->max_bucket+

最低0.47元/天 解锁文章
606

被折叠的 条评论
为什么被折叠?



