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

来源:互联网 发布:周杰伦湖南卫视知乎 编辑:程序博客网 时间:2024/06/10 15:14

本文转载于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,可能会有同名的情况)。

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

原创粉丝点击