调整使用底层HBase表的Hive查询

Ram*_*Ram 7 performance integration hadoop hbase hive

我在Hbase中有一个表让我们说"tbl",我想用Hive查询它.因此,我将表格映射到hive,如下所示:

CREATE EXTERNAL TABLE tbl(id string, data map<string,string>)
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key,data:")
TBLPROPERTIES("hbase.table.name" = "tbl");
Run Code Online (Sandbox Code Playgroud)

查询如下:

select * from tbl", "select id from tbl", "select id, data
from tbl
Run Code Online (Sandbox Code Playgroud)

真的很快

但查询喜欢

select id from tbl where substr(id, 0, 5) = "12345"

select id from tbl where data["777"] IS NOT NULL 
Run Code Online (Sandbox Code Playgroud)

非常慢.

相反,从Hbase shell运行时:

"scan 'tbl', {
COLUMNS=>'data', STARTROW='12345', ENDROW='12346'}" or
"scan 'tbl', { COLUMNS=>'data', "FILTER" =>
FilterList.new([qualifierFilter('777')])}"
Run Code Online (Sandbox Code Playgroud)

它闪电般快!

当我查看由jobtracker上的hive生成的mapred作业时,我发现"map.input.records"计算Hbase表中的所有项目,这意味着作业在它甚至启动任何映射器之前进行全表扫描!此外,我怀疑它在执行之前将所有数据从Hbase表复制到hdfs到mapper tmp输入文件夹.

所以,我的问题是 - 为什么hive的hbase存储处理程序不会将hive查询转换为适当的hbase函数?为什么它扫描所有记录然后使用"where"子句对它们进行切片?怎么改进?

任何提高Hive查询性能的建议(映射到HBase表).

我们可以在HBase表上创建二级索引吗?

我们正在使用HBase和Hive集成并尝试调整Hive查询的性能.

Rub*_*eda 11

很多问题!我会尽力回答所有问题并给你一些性能提示:

数据不会复制到HDFS,但HIVE生成的mapreduce作业会将其中间数据存储在HDFS中.

HBase不支持二级索引或备用查询路径(更多信息).

Hive会将所有内容转换为需要时间进行分发和初始化的MapReduce作业,如果你的行数非常少,那么Hbase shell中的简单SCAN操作比Hive查询更快,但是在大数据集上,分发作业数据节点之间是必须的.

从查询中提取开始和停止行键时,Hive HBase处理程序做得不是很好,查询substr(id, 0, 5) = "12345"不会使用开始和停止行键.

在执行查询之前,运行EXPLAIN [your_query];命令并检查filterExpr:部件,如果找不到,则查询将执行全表扫描.在旁注中,Filter Operator:将将所有表达式转换为适当的过滤器.

EXPLAIN SELECT * FROM tbl WHERE (id>='12345') AND (id<'12346')
STAGE PLANS:
  Stage: Stage-1
    Map Reduce
      Alias -> Map Operator Tree:
        tbl 
          TableScan
            alias: tbl 
            filterExpr:
                expr: ((id>= '12345') and (id < '12346'))
                type: boolean
            Filter Operator
                ....
Run Code Online (Sandbox Code Playgroud)

幸运的是,有一种简单的方法可以确保在查找行键前缀时使用启动和停止行键,只需转换substr(id, 0, 5) = "12345"为更简单的查询:id>="12345" AND id<"12346"它将被处理程序检测到并且启动和停止行键将提供给SCAN(12345,12346)


现在,这里有一些提示,以加快您的查询(很多):

  • 确保设置以下属性以利用批处理来减少RPC调用的数量(数量取决于列的大小)

    SET hbase.scan.cache=10000;

    SET hbase.client.scanner.cache=10000;

  • 确保设置以下属性以在任务跟踪器中运行分布式作业,而不是运行本地作业.

    SET mapred.job.tracker=[YOUR_JOB_TRACKER]:8021;

    SET hbase.zookeeper.quorum=[ZOOKEEPER_NODE_1],[ZOOKEEPER_NODE_2],[ZOOKEEPER_NODE_3];

  • 将SELECT语句的列数减少到最小.尽量不要SELECT *

  • 每当您想使用开始和停止行键来防止全表扫描时,始终提供key>=xkey<y表达式(不要使用BETWEEN运算符)

  • EXPLAIN SELECT在执行之前始终是您的查询.