Hbase之删除(delete)操作解析

本文主要讲解Hbase内部的数据删除策略,具体可以参考以下Lars Hofhansl的博客:

Scanning in HBase: Prefix Delete Marker

  • 针对一个指定的列的一个指定版本
  • 针对一个列的所有版本
  • 针对一个指定的列族的所有列(column qualifier)

当删除一整行数据的时候,Hbase内部会针对每个column family创建一个墓碑tombStone,注意,不是针对每个单独的Column Qualifier列。

Hbase的删除操作通过创建墓碑标识,举个例子,假设我们想要 删除一个row的数据,你可以指定一个版本,(Hbase的版本按照版本的long值大小倒序排序),假如不指定版本,那么默认使用currentTimeMills,这意味着删除该row下的所有的ColumnFamily下的所有的<=当前时间戳版本的所有的Cells。

Hbase从不会立刻修改或删除数据,比如一个删除操作不会立刻删除数据,而是给在存储文件中给相应的数据标记一个删除的状态,这是一种逻辑状态,这就意味着给这些需要删除的数据立了一个tombstone墓碑,具体删除数据的时候是在major compaction,在合并StoteFile的时候会将标记的数据以及对应的墓碑进行统一的清理移除,当删除的时候,你指定的version大于实际存储中所有的版本值,那么改行所有版本的数据都会被删除。

This blog entry describes how deletion works in HBase. One interesting piece of information not mentioned there is that version and column delete markers are ordered in line together with the KeyValues that they affect and family delete markers are always sorted to the beginning of their row.

Generally each column family is represented by a Store, which manages one or more StoreFiles. Scanning is a form of merge-sort performed by a RegionScanner, which merges results of one or more StoreScanners (one per family), who in turn merge results of one or more StoreFileScanners (one for each file for this family):

#以上是博客原文,具体翻译如下:
版本与列删除的maker按照顺序与他们影响的KV一起排序,然而列簇的删除maker通常排在他们的row的前面。
通常每个列簇代表一个store,而每个store管理着一个或者多个storeFile,scan是一个归并排序的操作,该操作由regionscanner完成,regionscanner将一个或多个storescanner扫描出来的结果进行合并排序(每个family一个storescanner),而storescanner又是将一个或者多个storeFilescanner查询出来的结果进行合并排序,每个storeFilescanner负责扫描该列簇下面的一个文件。

上图

Hbase中删除表 hbase删除字段_删除数据

总结

  • 即使我们只删除指定的column qualifier,我们也会去该row的开始位置查看是否有优先级最高的family delete marker的version >= 当前Cells的最大timestamp,然后再去找对应的具体column qualifer级别的delete marker。
  • 即使我们想要寻找一个column过往的版本,在扫描之前我们也需要寻找该column的开始位置,看是否有delete marker,就是墓碑。如果有墓碑,我们不算进扫描结果,因为该数据将会在major compaction的时候进行物理删除。

StoreFIle与HFile的关系,HFile实际是就是StoreFile,StoreFile Compaction之后最终存储在HDFS的存储文件也是HFile

以下是Lars作者的回答:

Hbase中删除表 hbase删除字段_存储文件_02

!思考一种情况,就是为什么我先执行的delete操作,然后执行put操作,为什么我put进去的数据get不到呢?

因为,假如你delete时指定的版本为T,此时Hbase默认给该row的每个列族添加了一个墓碑tombstone,<=T以下的数据都是不可见的,墓碑还处于生效状态,但是数据还没删除,此时你put进去一个version为T的数据,那么T也被列在墓碑作用的范围内,也是不可见的,假如delete操作与put操作之间进行了一次major compaction操作,那么该put数据的查询是会生效的。

/