我有一个包含8G
数据的 HBase 表。
当我对该表使用部分键扫描来检索给定键的值时,我得到几乎恒定的时间值检索。
当我使用 aGet
时,所花费的时间远远大于扫描。但是,当我查看代码时,我发现它Get
本身使用了Scan
.
谁能解释一下这个时差?
我有一个包含8G
数据的 HBase 表。
当我对该表使用部分键扫描来检索给定键的值时,我得到几乎恒定的时间值检索。
当我使用 aGet
时,所花费的时间远远大于扫描。但是,当我查看代码时,我发现它Get
本身使用了Scan
.
谁能解释一下这个时差?
正确,当您发出 Get 时,会在幕后进行扫描。Cloudera 的博文证实了这一点:“每次发出 get 或 scan 时,HBase 扫描(原文如此)通过每个文件来查找结果。”
我无法确认您的结果,但我认为线索可能在于您的“部分键扫描”。在比较部分键扫描和获取时,请记住,用于获取的行键可以是比用于扫描的部分键长得多的字符串。
在这种情况下,对于 Get,HBase 必须进行确定性查找以确定它需要匹配并获取它的行键的确切位置。但是使用部分键,HBase 不需要查找确切的键匹配,而只需要找到该键前缀的更近似位置。
答案是:视情况而定。我认为这将取决于:
以及可能的其他因素。
在后端 HRegion 上,Scan 和 Get 的数量几乎相同。它们最终都由 HRegion.RegionScannerImpl 执行。请注意,该类中的 get() 实例化了 RegionScanner - 类似于调用 Scan。
org.apache.hadoop.hbase.regionserver.HRegion.RegionScannerImpl
public List<Cell> get(Get get, boolean withCoprocessor)
throws IOException {
List<Cell> results = new ArrayList<Cell>();
// pre-get CP hook
if (withCoprocessor && (coprocessorHost != null)) {
if (coprocessorHost.preGet(get, results)) {
return results;
}
}
Scan scan = new Scan(get);
在 get() 的情况下,仅返回一行 - 通过调用scanner.next() 一次:
RegionScanner scanner = null;
try {
scanner = getScanner(scan);
scanner.next(results);