扫描和获取之间的性能差异?

问题描述 投票:0回答:3

我有一个包含

8G
数据的 HBase 表。

当我对该表使用部分键扫描来检索给定键的值时,我得到几乎恒定的时间值检索。

当我使用

Get
时,所花费的时间远远大于扫描。然而,当我查看代码时,我发现
Get
本身使用了一个
Scan
.

谁能解释一下这个时差?

hbase
3个回答
5
投票

正确,当您发出 Get 时,后台会进行扫描。 Cloudera 的博客文章 证实了这一点:“每次发出 get 或 scan 时,HBase 扫描(原文如此)遍历每个文件以找到结果。”

我无法确认你的结果,但我认为线索可能就在你的“部分按键扫描”中。当您比较部分键扫描和获取时,请记住,您用于获取的行键可以是比您用于扫描的部分键更长的字符串。

在那种情况下,对于 Get,HBase 必须进行确定性查找以确定它需要匹配并获取它的行键的确切位置。但是对于部分键,HBase 不需要查找精确的键匹配,只需要找到那个键前缀的更近似的位置。

答案是:视情况而定。我认为这将取决于:

  1. 您的行键“模式”或组合
  2. 获取密钥和扫描前缀的长度
  3. 你有多少个地区

可能还有其他因素。


2
投票

在后端 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);

0
投票

虽然cloudera文档表明Get是在幕后扫描

Get和Scan是除了手动解析HFiles之外的两种从HBase读取数据的方式。 Get 只是一个被 API 限制为一行的 Scan。 Scan 获取表的零行或多行

它们之间有一个微妙的区别,Get调用可以使用布隆过滤器而不是读取很少的StoreFiles。错误扫描无法使用这些布隆过滤器。 引用here

在 HBase 方面,Bloom 过滤器提供了一种轻量级的内存结构,可以将给定 Get 操作(Bloom 过滤器不适用于 Scans)的磁盘读取次数减少到仅可能包含所需 Row 的 StoreFiles。潜在的性能增益随着并行读取次数的增加而增加。

因此它完全取决于用例。扫描性能应小于或等于获取操作。

© www.soinside.com 2019 - 2024. All rights reserved.