使用 startrow 和 stoprow 如何不导致 HBase 中的完整 table 扫描?

How does the use of startrow and stoprow not result in a full table scan in HBase?

通常建议通过 startrowstoprow 使用范围扫描,而不是 Rowkey Prefix Filter(例如,here)。这样做的原因是因为 Rowkey Prefix Filter 会导致行键的完整 table 扫描,而通过 startrowstoprow 的范围扫描不会导致完整的 table 扫描。为什么不呢?大多数人说 "because the rowkey is stored in lexographical order," 当然,这并不能解释为什么 Rowkey Prefix Filter 不能利用它。

无论如何,通过 startrowstoprow 的范围扫描究竟是如何不导致对 rowkey 进行完整 table 扫描的?

以 python 中的这个小例子来说明为什么我不明白行键的字典顺序在避免完整 table 扫描方面有何意义:

rowkeys = ['a1', 'a2', 'a3', 'b1', 'b2', 'b3', 'c1', 'c2', 'c3']

def range_scan(startrow, stoprow):
    is_found = False
    for rowkey in rowkeys:
        if startrow <= rowkey < stoprow:
            is_found = True
            yield rowkey
        else:
            if is_found:
                raise StopIteration()

很明显,HBase的算法与此不同。怎么做到的?

TLDR:在使用 startrow 和 stoprow 进行范围扫描时,HBase 究竟如何避免完整 table 扫描?

在 HBase 中,一个 table 被分成区域。区域是由特定区域服务器提供服务的一组行。区域服务器具有(通常)来自多个 table 的多个区域,它处理请求。

因为行是按键排序的,所以在 hbase 主控中知道哪些开始键和停止键是每个区域的边界,并且可以在哪个区域服务器上查询该区域。

因此,如果使用显式开始和停止行完成扫描,则查询将仅定向到 regions/region 具有可能在请求范围内的键的服务器。

如果查询有 'small' 个键范围,那么您会发现在几乎所有查询中,只访问一个区域。

一个 HBase table 有几十个区域是很常见的,通过使用开始和停止行来限制扫描,您可能会发现 table 的 100 个区域中有 99 个区域甚至不知道对 table 的查询已经完成。