为什么大规模数据处理很少用到hash

本文探讨了数据库中B+树和HASH作为索引结构的应用场景及优劣对比。针对不同类型的查询需求,分析了两种索引方式的特点,并详细解释了B+树如何更好地支持范围查询和多表联接操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文转载于SMTH的SET版,由大牛pennyliang所作。觉着写得真的挺好,就厚颜无耻的拿过来了。

我们首先从数据库的角度看,我们知道mysql的基本结构一般是B+树,为什么常用的不是HASH呢?从几个方面来看。

一般我们存储数据的方法可以抽象为。
primay key, candiate key1,candidate key2,...->value{field1,field2,...}

如果我们支持的仅仅是
select field1 from table where primay key=XXX
那么完全可以用HASH来做,而且可能更好。

但如果是这样的查询呢?
select field1 from table where primay key>XX and key <YY
显然用普通的HASH,就很难处理了,需要枚举出XX到YY全部的key,一个个的去尝试。
在比如两个表相交的场合,用HASH来做也会很伤,很多不必要的计算。

因此就引出了一个问题,需要保序(order preserved),可以将哈希函数做到完美哈希函数来实现保序,这个在即将出版的MG一书中有精彩论述,而且做出一个完美哈希函数代价极大,只能对静态集合,长期使用的场合使用,比如静态字典。

B+树很好的解决了这个问题,value都在叶子节点上,而且是保序的,因此很容易处理这种查询,但B+树需要有非叶节点的开销,插入,删除都会有一定代价。

对于索引一次创建,没有插入和删除的需求的话,最朴素的方法,莫过于直接排序,即我们可以把此前的结构转化为。
primary key value
key1 v1
key2 v2
key3 v3
... ...
keyn vn
每个key都是排好序的,这一点很重要,其余的candidate key也是类似处理。每个索引用一个索引文件来表示。

如果value特别巨大,这里可以存放的是value在硬盘的偏移(linux的话还可以直接写设备,直接用设备的偏移来表示数据的位置)

排序为优化创造了很好的条件,比如我们需要进行一个这样的查询:
select table1_key,table2_key,table1_value from table1,table2
where table1_key=table2_key
由于这两个表都是按照key排序的,这样两个有序的索引求交可以非常快速,只需要O(min(length(table1),length(table2))的时间复杂度。

排序的方法在处理duplicate key也非常有利,仅仅是相同key的位置放在了一起,而哈希还需要特别处理这种情况(注意这种不是冲突,比如用学生姓名做candidate index,可能会有同名的情况)。

另外排序的方法是最节省的了,几乎没有浪费,性价比高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值