HBase 扫描很慢

标签 hbase phoenix

问题

我正在尝试使用 Phoenix 构建二级索引。创建索引需要几个小时。这似乎是由于 HBase 扫描缓慢,因为我注意到以下性能:

  • 我可能需要 2 个小时来扫描表,而其他开发人员报告说对于较大的表(1 亿行)需要几分钟。
  • HBase shell 能够以大约 1 的频率计算行数。每秒 10.000 的速率,这意味着计算该表的所有行需要 3800 秒(>1 小时!)。

  • 都带有 HBase shell 和 Java 扫描器。

    注意:GET(by rowkey) 操作具有良好的性能(约 0.5 秒)。

    语境
  • 3800 万行/1000 列/单列族/96Go 使用 GZ 压缩。
  • 集群有 6 个节点(126Go RAM,24 核)和 5 个区域服务器。
  • Hortonworks 数据平台 2.2.0


  • 故障排除

    基于 HBase 书( http://hbase.apache.org/book.html#performance ),这是我已经检查过的内容:

    1) 硬件
  • IO(磁盘)
  • NMon 表示磁盘的繁忙度永远不会超过 80%,最常见的是在 0 到 20% 之间
  • Top 说 HBase JVM 没有交换(检查了 5 个 RS 中的 2 个)
  • IO(network) : 每个节点的主动接口(interface)都站在同一个交换机上(所有第二个被动接口(interface)都插在不同的交换机上)

  • 2) 虚拟机
  • GC 暂停正常(每分钟左右暂停几毫秒)
  • 堆看起来不错(在接近极限时没有达到峰值)
  • CPU 出奇地低:从不超过 10%
  • 主题:
  • 事件线程(10 个“RpServe.reader=N”+ 其他几个)显示无争用
  • 很多停放的线程什么都不做(60 个“DefaultRpcServer.handler=n”,其他大约 15 个)
  • 没有任何线程状态的大量 IPC 客户端列表

  • 3) 数据
  • 使用 Hive + completebulkload 批量加载。
  • 地区数量 :
  • 13 个区域意味着每个 RS 有 2 到 3 个大区域,这是预期的。
  • 强制执行主要压缩后,扫描性能保持不变。
  • 区域大小相当均匀:11 个区域为 4,5Go (+/-0.5),2 个区域为 2,5Go

  • 4)HBase配置
  • 大多数配置保持不变。
  • HBase env 仅指示 JMX 控制台的端口
  • HBase-site 对 Phoenix 的设置很少
  • 一些对我来说还不错的参数
  • hbase.hregion.memstore.block.multiplier
  • hbase.hregion.memstore.flush.size:134217728 字节(134Go)
  • Xmx 的 Xmn 比率:.2 Xmn 最大值:512 Mb Xms:6144m
  • hbase.regionserver.global.memstore.lowerLimit : 0.38
  • hbase.hstore.compactionTreshold:3
  • hfile.block.cache.size : 0.4(块缓存大小占堆的百分比)
  • 最大 HStoreFile (hbase.hregion.max.filesize) : 10 go (10737418240)
  • 客户端扫描器缓存:100 行 zookeeper 超时:30 秒
  • 客户端最大键值大小:10 个月
  • hbase.regionserver.global.memstore.lowerLimit : 0.38
  • hbase.regionserver.global.memstore.upperLimit : 0.40
  • hstore 阻止存储文件:10
  • hbase.hregion.memstore.mslab.enabled:
  • 启用 hbase.hregion.majorcompaction.jitter : 0.5
  • 尝试了以下配置更改而对性能没有任何影响
  • hbase-env.sh :尝试增加 HBASE_HEAPSIZE=6144(因为它默认为 1000)
  • hbase-site.xml :
  • hbase.ipc.server.callqueue.read.ratio : 0.9
  • hbase.ipc.server.callqueue.scan.ratio : 0.9

  • 5)日志说没什么用

    cat hbase-hbase-master-cox.log | grep "2015-05-11.*ERROR"

    cat hbase-hbase-regionserver-*.log | grep "2015-05-11.*ERROR"

    什么都不打印

    打印警告显示不相关的错误

    2015-05-11 17:11:10,544 WARN [B.DefaultRpcServer.handler=8,queue=2,port=60020] 短路。ShortCircuitCache:ShortCircuitCache(0x2aca5fca):无法加载 1074749724_BP-71737375173781872到 InvalidToken 异常。

    2015-05-11 17:09:12,848 警告 [regionserver60020-smallCompactions-1430754386533] hbase.HBaseConfiguration:配置选项“hbase.regionserver.lease.period”已弃用。相反,使用“hbase.client.scanner.timeout.period”

    最佳答案

    明白了:关键是将“热”内容与“冷”内容分开到单独的列族中。列族用于将列存储在单独的 HFile 中,因此我们可以将一个列族用于索引(或经常读取)的列,而另一个列族(因此是文件)用于所有其他列。

    第一步:看到较小的列族扫描速度更快

    我们只是丢弃冷内容来构建一个较小的列族(1655 列 -> 7 列)。

    中型表扫描的性能:

  • [37.876.602 行,1655 列] 扫描 1000 行花了 39.4750
  • [76.611.463 行,7 列] 扫描 1000 行花了 1.8620

  • 评论 :
  • 当我们扫描前 1000 行时,可以忽略总行数
  • 由于从 Hbase shell 扫描会在控制台中打印内容,因此存在大行开销

  • 第二步:生成多族HTable

    我们通过从 Hive 生成​​ HFile 来进行批量加载。虽然文档说 we can't generate one multi family table ,可以单独生成HFiles:
    create table mytable_f1 (UUID string, source_col1, source_col2)
    ...
    TBLPROPERTIES('hfile.family.path' = 'tmp/mytable/**f1**');
    
    create table mytable_f1 (UUID string, source_col3, source_col4)
    ...
    TBLPROPERTIES('hfile.family.path' = 'tmp/mytable/f2');
    

    然后像往常一样简单地调用导入命令:
    hadoop jar [hbase-server-jar] completebulkload /tmp/mytable mytable
    

    关于HBase 扫描很慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30076752/

    相关文章:

    rest - 无法通过REST获取表数据

    hadoop - Apache Phoenix中的Hbase过滤器

    java - 如何在 java 中创建 HBbase 复合过滤器

    java - hbase 和 phoenix 不同 jar 的 Gradle 解析策略

    php - 如何将Apache Phoenix与laravel或PHP集成?

    hbase - 如何在不丢失 HBase 数据的情况下更改 Apache Phoenix 中列的数据类型?

    hadoop - 自定义比较器中的 Hbase 传递值

    java - Phoenix连接运行一段时间后抛出错误消息 “Failed to find any Kerberos tgt”

    hadoop - 获取trafodion中最后插入的行ID

    hadoop - 带有Spark 1.3.1的Apache phoenix 4.5.1 ClassNotFoundException