尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Hive on HBase 实战:外部表映射、Bulk Load 与性能优化

Hive on HBase 实战:外部表映射、Bulk Load 与性能优化 Hive 和 HBase 这两个名字摆在一起不少做数据平台的同学第一反应是这俩不是一个体系的活吗。我在华为云 MRS 上第一次把 Hive 表和 HBase 表打通起因是一个挺具体的麻烦业务侧要一份按用户维度的宽表实时接口那边要按 rowkey 毫秒级取数离线这边又要跑分群和留存统计。两个团队各维护一套数据同步延迟、口径不一致的问题一直没消停。后来把 HBase 当存储底座Hive 侧用 HBaseStorageHandler 把 HBase 表直接映射成外部表一条 SQL 就能把 T1 的统计结果写回去实时接口一行代码没改就读到了新标签。这套方案在华为云 MRS 集群上跑了大半年踩过的坑不算少从NoClassDefFoundError到 Kerberos 代理用户、从 rowkey 热点到 bulk load 目录被清掉基本都经历了一遍。下面我把整套做法和排查思路摊开讲为什么这么设计、建表语句每个字段是什么意思、参数该调到多少、报错了往哪查。刚接触 Hive 和 HBase 的新手能照着抄已经在维护集群的老手也能捞到几条能省半天时间的经验。1. 先搞清楚为什么非要把 Hive 和 HBase 凑到一起1.1 两个系统的脾气完全不同Hive 的定位是 SQL on Hadoop面向的是大批量分析。它把 SQL 翻译成 MapReduce、Tez 或 Spark 作业扫描方式以全表或大范围扫描为主讲究的是吞吐量单条查询延迟从几十秒到几分钟都算正常。数据落在 HDFS 或者对象存储上schema 存在 Metastore 里列式存储、分区裁剪、谓词下推是它的拿手好戏。HBase 是另一套路子它是 BigTable 的开源实现本质是构建在 HDFS 之上的 KV 存储。数据按 rowkey 字典序排列天然支持按 rowkey 的单行查询和范围 scan延迟能压到毫秒级。它支持列族Column Family、列限定符Qualifier、多时间戳版本写多读少、随机读写的场景是它的主场。打个生活化的比方Hive 像仓库的年度盘点一次要把所有货架翻一遍慢但全HBase 像便利店的货架你要哪瓶水伸手就拿到快但只知道怎么按位置找。这两个能力互补所以才有整合的价值。1.2 整合真正解决的三个场景我在实际项目里遇到的需求基本逃不出这三类。第一类是离线结果回写。用户画像标签、推荐候选集、风控名单这类数据通常是离线算出来的Hive 侧跑几十张表的 join 和聚合但消费方是线上服务要求按 userId 毫秒级命中。这时候用 Hive 直接 INSERT 到 HBase 映射表离线链路不用额外写 MR 程序运维成本直接砍掉一大块。第二类是明细存在 HBase分析走 Hive。有些业务的明细数据天生量大且要频繁点查放在 HBase 里。但产品同学时不时想跑个 ad-hoc 分析总不能每次都把全量数据同步一份到 HDFS。用 Hive on HBase 直接查虽然比原生 Hive 表慢但省掉了同步链路和数据冗余。第三类是小维表 join。把一张几千行的维表放 HBaseHive 侧的大表去关联它。这种用法要谨慎因为 Hive 关联 HBase 表时每行都可能触发一次 HBase 请求网络往返开销很吓人。真要用得配合 HBase 端的 BlockCache 和客户端缓存调优或者干脆改用 MapJoin 把维表加载进内存。反过来说什么场景不该用需要事务保证的、需要频繁更新同一 rowkey 再批量分析的、以及大表 join 大表的这些老老实实用 Hive 原生表或者别的存储更合适。1.3 底层机制StorageHandler、InputFormat 和 SerDe整合这件事看着像魔法拆开看其实就三个组件在干活。HBaseStorageHandler实现了 Hive 的StorageHandler接口负责三件事把 Hive 表的元数据和 HBase 表对应起来、指定输入输出格式、指定序列化反序列化器。类名是org.apache.hadoop.hive.hbase.HBaseStorageHandler在hive-hbase-handler-x.x.x.jar里。输入侧是HiveHBaseTableInputFormat。它生成 InputSplit 的方式和读 HDFS 文件完全不同——它直接问 HBase 要 region 分布一个 region 对应一个 split。这意味着你的并行度不是由文件大小决定的而是由 region 数量决定的。一张只有 3 个 region 的 HBase 表你就算给再多资源最多也就起 3 个 map。这个认知很关键后面性能优化会反复用到。输出侧是HiveHBaseTableOutputFormat本质是把每行记录转成Put对象要么逐条 RPC 写要么走 HFile 批量导入。SerDe 是HBaseSerDe它管的是映射关系Hive 的第几列对应 HBase 的哪个列族、哪个限定符、是当字符串处理还是当二进制处理。绝大多数读出来乱码写入类型不对的问题根子都在这个映射上。2. 环境准备版本、依赖与配置分发2.1 版本兼容性是最容易翻车的第一道坎整合能不能跑起来八成取决于版本组合。我的经验是组件推荐组合说明Hive3.1.x3.x 对 HBase 2.x 的适配明显好于 2.xHBase2.2.x / 2.3.x客户端和服务端大版本必须一致Hadoop3.1.x 及以上与 HBase 2.x 配套JDK8Hive 和 HBase 在这个组合下最稳华为云 MRS 集群的话选 3.x 版本的集群Hive 和 HBase 的版本搭配是官方验证过的省掉很多试错成本。如果是自建集群特别注意 Hive 2.x HBase 2.x 这个组合hbase-shaded-client和hbase-client的类冲突会让人抓狂典型表现是NoSuchMethodError或者ClassNotFoundException。还有一个必须确认的点hive-hbase-handler-*.jar必须在 Hive 的 classpath 里。MRS 客户端里这个包一般已经在/opt/client/Hive/Beeline/lib/或者 Hive 服务端的 lib 目录下自建集群经常忘。2.2 在华为云 MRS 上把连接参数捞全整合的本质是 Hive 作为 HBase 客户端去连 HBase所以 Hive 侧必须知道 HBase 的 ZooKeeper 地址。在 MRS 控制台进集群详情找到 ZooKeeper 组件能看到 quorum 列表通常是三个节点的主机名加端口。需要记下来的参数有四个hbase.zookeeper.quorumZK 地址列表逗号分隔hbase.zookeeper.property.clientPort默认 2181zookeeper.znode.parentMRS 集群一般是/hbase自建集群有时候是/hbase-unsecure这个填错会一直报连不上hbase.client.retries.number重试次数默认 15如果 Hive 和 HBase 不在同一套集群比如 Hive 在 A 集群、HBase 在 B 集群还需要确保网络互通并且 Hive 侧的 hosts 能解析 HBase 所有 RegionServer 和 ZK 节点的主机名。这一条听起来很基础但我见过至少三次连不上最后发现是 DNS 解析问题。2.3 三处必须做的配置改动第一处让 Hive 节点能读到 hbase-site.xml。MRS 客户端的 HBase 配置在/opt/client/HBase/hbase/conf/hbase-site.xml。最稳妥的做法是把这个文件软链或者复制到 Hive 的 conf 目录然后确认每个 NodeManager 节点的 classpath 里都能找到它——因为真正干活的 map 任务是跑在 NodeManager 上的HiveServer2 节点配好了不代表能跑通。MRS 有同步配置功能改动后记得下发。第二处hive-site.xml 里补 HBase 连接参数。property namehbase.zookeeper.quorum/name valuenode-1,node-2,node-3/value /property property namezookeeper.znode.parent/name value/hbase/value /property临时验证的话也可以直接在 Hive CLI 会话里set不用改文件set hbase.zookeeper.quorumnode-1,node-2,node-3; set zookeeper.znode.parent/hbase;但要注意会话级的 set 只在当前会话有效HiveServer2 的每个连接都要重新设所以生产环境还是写进配置文件靠谱。改完 hive-site.xml 必须重启 HiveServer2。第三处安全模式下的代理用户。MRS 安全模式集群启用了 KerberosHiveServer2 以 hive 用户身份去访问 HBase需要在 core-site.xml 里给 hive 开代理权限property namehadoop.proxyuser.hive.hosts/name value*/value /property property namehadoop.proxyuser.hive.groups/name value*/value /propertyMRS 默认集群里一般已经配好了自建安全集群经常漏。漏了的表现是任务提交后卡住日志里能看到GSS initiate failed或者SaslException。注意Kerberos 过期是个高频坑。长期跑定时任务的同学记得给 keytab 加自动续期或者定期 kinit不然某天凌晨任务集体失败排查半天才发现是票据过期。3. 建表实操把 HBase 表映射成 Hive 外部表3.1 一条完整的建表语句逐字段拆开看先给一条我实际在用的语句然后逐段解释。CREATE EXTERNAL TABLE ods_user_hbase ( rowkey string COMMENT HBase rowkey, uid string COMMENT 用户ID, name string COMMENT 昵称, age int COMMENT 年龄, tags mapstring,string COMMENT 动态标签列族 ) STORED BY org.apache.hadoop.hive.hbase.HBaseStorageHandler WITH SERDEPROPERTIES ( hbase.columns.mapping :key,info:uid,info:name,info:age,tag: ) TBLPROPERTIES ( hbase.table.name user_profile, hbase.mapred.output.outputtable user_profile, hbase.table.default.storage.type string );关于 EXTERNAL。用 EXTERNAL 建的映射表DROP 的时候只删 Hive Metastore 里的元数据HBase 那张表原封不动。不用 EXTERNAL 的话DROP TABLE 会把 HBase 表一起删掉——我第一次测试的时候就这么把一张测试表清空了幸亏不是生产。所以映射已有 HBase 表的场景一律加 EXTERNAL。关于:key。它代表 rowkey必须放在hbase.columns.mapping的第一位而且整条映射里只能出现一次。hbase.columns.mapping里的项数必须和 Hive 表的列数严格相等少一个多一个都会在编译期报错java.lang.RuntimeException: Column mapping size 4 does not match number of columns 5 of table这个报错信息其实很直白但很多人建表时习惯性加个分区列或者备注列列数就对不上了。关于tag:。结尾带冒号、后面什么都不写表示把整个tag列族映射成一个mapstring,stringkey 是列限定符value 是值。这种写法适合字段动态变化、列很稀疏的场景。对应的 Hive 列类型必须是mapstring,string写错了运行时报类型转换异常。关于hbase.table.name。指定对应的 HBase 表名如果不写默认用 Hive 表名。HBase 表名区分大小写映射时要和 HBase 侧完全一致。另外要提醒一句HBase 的 namespace 也要带上比如dim:user_profile只写表名会找错地方。关于hbase.table.default.storage.type。这个属性控制 Hive 往 HBase 写数据时的序列化方式string表示按字符串写binary表示按二进制写。默认是string和大多数人的直觉一致建议显式写出来避免误判。3.2 两种映射粒度怎么选映射方式写法示例适用场景坑点逐列映射info:uid,info:name字段固定、类型明确加字段要改 Hive 表结构列族整体映射info:字段动态、稀疏、经常加列Hive 侧只能当 map 处理不能直接 where我在生产里更偏向逐列映射。原因是列族映射虽然灵活但 Hive 侧拿到的是一整个 map想按某个字段过滤得先explode展开SQL 写起来别扭而且没法走列裁剪IO 开销更大。只有在字段确实频繁变化、数量不确定的场景比如设备属性上报这种才用列族映射。3.3 时间戳、二进制与表名变更HBase 天然支持多版本映射时可以用:timestamp保留列拿到时间戳CREATE EXTERNAL TABLE ods_user_hbase_ts ( rowkey string, uid string, ts bigint ) STORED BY org.apache.hadoop.hive.hbase.HBaseStorageHandler WITH SERDEPROPERTIES ( hbase.columns.mapping :key,info:uid,:timestamp ) TBLPROPERTIES (hbase.table.name user_profile);:timestamp对应的 Hive 列类型是bigint。查询时 Hive 只会返回每个单元格的最新版本想拿历史版本得在 HBase 侧单独处理Hive 这层拿不到。二进制映射。如果 HBase 里的数据是用Bytes.toLong()之类的方式写的二进制Hive 直接读会是一串乱码。这时候在映射后面加#b后缀hbase.columns.mapping :key,info:uid,info:age#b加了#b之后SerDe 会按二进制方式解析int 就能正常读出来。反过来如果 HBase 存的是字符串 18你映射时加#b读出来就是乱码。映射的序列化方式和数据实际存储方式必须匹配这是判断乱码问题的第一原则。表名变更。Hive 里ALTER TABLE ods_user_hbase RENAME TO ods_user_hbase_v2只改 Metastore 里的名字hbase.table.name属性不会跟着变HBase 侧的表名也不动。这一点是好事也是坑好处是改 Hive 表名不影响 HBase坑在于如果你期望改个名就换个 HBase 表那是想多了得手动改 TBLPROPERTIES 再MSCK REPAIR之类而且改完要重新验证映射。4. 数据双向流动写入、查询与性能优化4.1 Hive 写 HBase 的三条路径路径一普通 INSERT。最简单Hive 把每行转成 Put 逐条发 RPC。INSERT INTO TABLE ods_user_hbase SELECT rowkey, uid, name, age, tags FROM dws_user_wide;适合数据量几十万到几百万、对写入耗时不太敏感的场景。缺点是 RPC 往返多几千万行的话能跑到你怀疑人生。路径二Bulk Load。大数量导入的正解。原理是先让 Hive 在 HDFS 上生成 HFile 格式的文件再用LoadIncrementalHFiles直接把这些文件搬进 HBase完全绕开写路径的 WAL 和 MemStore速度能差一个数量级。set hive.hbase.bulktrue; set hbase.client.write.buffer8388608; INSERT OVERWRITE TABLE ods_user_hbase SELECT rowkey, uid, name, age, tags FROM dws_user_wide;Bulk Load 有几条硬性限制需要注意目标 HBase 表最好是空的或者刚重建的因为这条路走的是文件级加载不做版本合并HFile 的 rowkey 必须有序Hive 侧输出天然有序所以问题不大还有临时输出目录的权限Hive 的提交用户要对它有写权限否则会报Permission denied。提示Bulk Load 期间如果作业失败重跑HDFS 上残留的临时 HFile 目录要先清掉不然第二次加载会把旧数据一起带进去。路径三先落 Hive 表再定时同步。有些团队出于稳定性考虑不让 Hive 直接写 HBase而是先用 Hive 生成结果表再用独立程序批量导入。好处是链路解耦、失败可控坏处是多一跳延迟。选哪种取决于团队对实时性的容忍度。4.2 查询下推、scan 调参与行列转换Hive 查 HBase 表最怕的就是看起来只查几行实际扫了全表。要理解几件事谓词下推很有限。只有作用在 rowkey 上的等值或前缀条件才有机会被翻译成 HBase 的 Scan filter。像WHERE uid 12345这种对普通列的条件Hive 是把所有数据拉到 Map 端再过滤的实际扫的还是全表。-- 有机会下推走 rowkey 范围 scan SELECT * FROM ods_user_hbase WHERE rowkey u_10001; SELECT * FROM ods_user_hbase WHERE rowkey LIKE u_100%; -- 扫全表uid 不是 rowkey SELECT * FROM ods_user_hbase WHERE uid 10001;列裁剪是有用的。Hive 只会读取 SELECT 和 WHERE 里用到的列所以千万别写SELECT *尤其是列族很多、列很稀疏的表多余的列会带来大量无意义的 HBase 读取。scan 缓存要调大。hbase.client.scanner.caching控制一次 RPC 从服务端取多少行默认 100。对于批量分析场景调到 500 到 1000 能显著减少 RPC 次数。set hbase.client.scanner.caching1000; set hbase.rpc.timeout120000; set hbase.client.scanner.timeout.period120000;行列转换。如果映射用了列族整体映射Hive 侧拿到的是 map想展开成多行用explodeSELECT rowkey, tag_k, tag_v FROM ods_user_hbase LATERAL VIEW explode(tags) t AS tag_k, tag_v;反过来离线算出来的多行标签要写回 HBase 的 map 列用collect_list或map聚合SELECT uid AS rowkey, map(tag_name, tag_value) AS tags FROM dws_user_tags GROUP BY uid;这两招在处理画像标签表时特别常用因为标签天然是 key-value 结构和 HBase 的列族模型天然契合。4.3 性能参数清单和并行度计算下面这张表是我压测后固定下来的一套配置供参考。参数默认值建议值作用hbase.client.scanner.caching1001000减少 scan 的 RPC 次数hbase.client.write.buffer2MB8MB提高批量写入吞吐hive.hbase.bulkfalsetrue大导入时走 HFile 批量加载hbase.rpc.timeout60000120000避免大 scan 超时hbase.client.scanner.timeout.period60000120000同上hive.hbase.wal.enabledtrue批量导入时 false关 WAL 提速代价是故障可能丢数据并行度怎么算。前面说过map 数由 HBase region 数决定。假设有张表 500GB每个 region 10GB那就是 50 个 map。如果单个 map 的读取吞吐是 30MB/s一个 map 要跑 10GB / 30MB/s ≈ 341 秒。想把总时长压到 3 分钟内就得把 region 数提到 100 以上方法是在建 HBase 表时预分区pre-split或者后续做 region split。这个计算不精确但足够帮你判断瓶颈在哪如果发现只有几个 map 在跑别急着加资源先去看 region 数。我见过有同学给一个 5 个 region 的表申请了 200 个 container跑完还是那么慢白花钱。5. 踩坑实录常见报错与排查速查表5.1 NoClassDefFoundError 和类冲突类问题这类报错的信息通常长这样java.lang.NoClassDefFoundError: org/apache/hadoop/hbase/HBaseConfiguration或者java.lang.NoSuchMethodError: org.apache.hadoop.hbase.client.Put.init(...)第一种是彻底找不到类最常见的原因是hive-hbase-handler或hbase-client没在 Hive 的 lib 目录或者客户端提交任务时用的 classpath 和集群不一致。解决思路先确认 Hive 安装目录 lib 下有没有hive-hbase-handler-*.jar再确认hbase-site.xml和 HBase 相关 jar 在 NodeManager 节点的 classpath 里。第二种是方法签名对不上典型的多版本 jar 冲突。Hive 2.x 自带一份老版本 hbase clientHBase 2.x 又依赖hbase-shaded-client两套类加载时谁先谁后看运气。排查方法是打印 classpath搜hbase-client和hbase-shaded-client是不是同时存在如果是把老的那个从 Hive auxlib 或 lib 里挪走。MRS 集群上这个组合是验证过的自建集群才需要折腾。5.2 连接类问题的排查顺序连不上 HBase 的报错五花八门我总结了一个固定的排查顺序按这个顺序走基本能定位看异常第一行。Connection refused是网络或端口问题KeeperErrorCode NoNode是 znode parent 不对GSS initiate failed是 Kerberos。在 Hive 节点上 telnet ZK 端口。telnet zk-host 2181通不通一下就知道网络有没有问题。确认 znode parent。用echo ls / | zkCli.sh -server zk-host:2181看根目录下有没有/hbase。填成/hbase-unsecure是自建集群的高频错误。确认 hosts 解析。ping一下 RegionServer 的主机名解析不了就在/etc/hosts里补。确认票据。安全模式下klist看一下票据有没有过期。5.3 数据类型和空值的那些隐形陷阱静默丢数据是最恶心的。HBase 里某个列存的是abcHive 侧映射成int读的时候不会报错直接给你返回 null。表面上看任务成功了实际上数据已经错了。所以映射前一定要抽样确认 HBase 里的实际存储格式别拍脑袋定类型。HBase 没有 null 的概念。一个列如果是空的读出来 Hive 侧就是 null。反过来Hive 写 null 到 HBase实际上是不会写这个单元格。这个行为在做count(列)统计的时候要特别注意结果可能和你在 Hive 原生表上算出来的不一样。rowkey 只能是 string 或二进制。用:key映射时Hive 列类型必须兼容。如果 HBase 的 rowkey 是拿Bytes.toBytes(long)生成的Hive 侧就得用对应的二进制映射方式否则读出来的 rowkey 和你在 HBase shell 里看到的完全不一样。5.4 常见问题速查表现象可能原因排查动作解决方案建表报列数不匹配mapping 项数和 Hive 列数不一致数一遍 mapping 里的逗号补齐或删掉多余列查询结果全是 null数据类型映射错、序列化方式不匹配用 HBase shell 抽样看原始值调整映射类型或加#b任务只有 1 到 3 个 mapHBase 表 region 数太少describe看 region 分布预分区或做 split写入特别慢逐条 Put走 RPC看写入模式切 Bulk Load报 Permission denied输出目录权限不足看报错里的路径归属调整目录属主或换提交用户报 GSS initiate failedKerberos 票据过期或代理未配klist、查 core-site.xml重新 kinit 或补代理配置建表成功但查询报找不到表namespace 没写或表名大小写不符HBase shell 里list确认补 namespace 前缀列族映射后无法按字段过滤用了整体列族映射看 SQL 是否 explode改逐列映射或先展开5.5 数据倾斜和 rowkey 热点HBase 的数据倾斜和 Hive 侧的倾斜表现不太一样但根子都是分布不均。HBase 侧最典型的是 rowkey 单调递增。比如用时间戳当 rowkey 前缀所有新数据都往最后一个 region 写前面的 region 闲着最后一个 region 扛全部流量。解决办法有几种rowkey 加随机前缀salt_加 1 到 10 的随机数、把时间戳反转后再拼、或者用 userId 的哈希值做前缀。代价是范围查询变麻烦因为相邻的数据不再物理相邻。Hive 侧的倾斜出现在 join 和 group by 上set hive.optimize.skewjointrue配合hive.skewjoin.key100000能缓解一部分。但如果倾斜的根源在 HBase 的 region 分布上调 Hive 参数是治标不治本得从 rowkey 设计入手。6. 几个容易被忽略的运维细节6.1 权限和审计如果用 Ranger 做权限管理HBase 表和 Hive 映射表的权限是分开的。也就是说用户能查 Hive 映射表前提是他既有 Hive 侧的 SELECT 权限又有 HBase 侧对应表的读权限。这一条在新人上手时经常卡住报错还特别模糊只说没有权限不告诉你是哪一侧缺。6.2 TTL 和 Hive 分区的错配HBase 表通常设了 TTL过期数据会自动清理。Hive 侧的映射表没有这个概念查询时看到的数据条数会随着 TTL 到期而减少。如果下游有对账逻辑这个行为一定要提前说明不然会以为是数据丢了。另外 HBase 表的 TTL 是按单元格时间戳算的而 Hive 写入时用的是什么时间戳取决于映射方式和写入路径Bulk Load 场景下尤其要确认清楚。6.3 元数据变更的同步成本HBase 侧新增一个列限定符Hive 映射表不会自动感知——逐列映射的话得ALTER TABLE ... ADD COLUMNS改映射列族映射的话天然就能读到。同理HBase 表重建比如清空重建之后Hive 侧的统计信息会失真ANALYZE TABLE要重新跑。这些变更最好纳入发布流程别让某个人的手动操作成为不可追溯的例外。6.4 Hive on Tez 的兼容性Hive 配置 Tez 引擎之后查询 HBase 映射表的行为和 MapReduce 引擎有差异某些版本上会出现切分异常或者任务卡住。我的做法是涉及 HBase 映射表的作业显式指定用 MapReduce 引擎别图 Tez 那点速度稳字当头。set hive.execution.enginemr;在 MRS 上跑的时候我还发现同一个会话里先跑了 Tez 作业再跑 HBase 映射表的查询偶尔会出现连接池复用导致的超时所以这类作业我一般单独起会话做完就关。7. 我在这套方案里踩出来的几条经验说几条文档里不太会写、但实际很影响效率的东西。第一条验证链路先跑通最小闭环。建表、写一行、读一行这三步通了再上大数据量。我最开始急着导几千万行结果报错一堆根本分不清是权限问题、映射问题还是数据问题。后来改成先用 Hive 插一行进去用 HBase shellget确认写对了再select读回来确认读对了整条链路验证完再放大数据量排查效率高很多。第二条HBase 表结构尽量先在 HBase 侧建好。Hive 建映射表时如果 HBase 表不存在会自动创建但列族的压缩算法、TTL、预分区这些属性用的都是默认值后面想改得alter甚至重建。生产环境我都是先在 HBase shell 里把表和预分区建好Hive 只做映射把它当成一个视图用。第三条别把 Hive on HBase 当万能查询入口。它适合的是离线算完写进去和低频少量查询不适合给 BI 工具做交互式查询。真要给分析同学用中间套一层物化视图或者定时同步到 Hive 原生表会更靠谱。我们现在的做法是HBase 负责在线服务Hive 原生表负责分析两者之间用映射表做数据搬运各司其职。第四条监控指标要看对地方。整合链路的瓶颈经常不在 Hive 侧而在 HBase 侧。Hive 任务变慢的时候先去看 HBase 的 RegionServer 指标读写请求数、MemStore 大小、Region 数、GC 时间。有一次我们排查一个Hive 查询突然变慢的问题最后发现是某个 RegionServer 的 region 数涨到了两千多单个 RegionServer 扛不住和 Hive 一点关系都没有。第五条参数别一次改一堆。性能调优的时候hbase.client.scanner.caching、write.buffer、map 数这些参数互相影响一次改三四个最后根本不知道是哪个起了作用。我的习惯是一次只动一个跑同样的数据集对比耗时记录下来几轮之后就有自己的经验值了。上面表格里的建议值就是我们这么一轮轮试出来的换个数据规模可能就不适用还是要结合自己的场景实测。
返回列表