0.概述

Hive对外提供了StorageHandler接口,提供了访问各种存储组件中的数据的能力。Hbase提供了HbaseStorageHandler,使得hive可以通过建立外部映射表访问hbase中的数据。但是,公司CDH集群的版本比较低,不支持新版hive原生的JdbcStorageHandler。因而要访问JDBC数据源中的数据,只能通过添加第三方类库实现。

1.Hive 访问Hbase

use ods_sdb;
create external table if not exists ods_sdb.$v_table(
ajbs string comment '标识',
hytcyqdrq string comment '合议庭成员确定日期',
splcbgkyy string comment '审判流程不公开原因',
ajgyxx_stm string comment '实体码',
bygksplc string comment '不宜公开审判流程',
jbfy string comment '经办法院',
labmbs string comment '立案部门标识',
splcygk string comment '审判流程已公开',
ajgyxx_ajbs string comment '案件标识',
ajmc string comment '案件名称',
stm string comment '实体码',
cbbmbs string comment '承办部门标识'
) comment '概要信息'
stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
with serdeproperties (
'hbase.columns.mapping' = ':key,f:anjiangaiyaoxinxi.heyitingchengyuanquedingriqi,f:anjiangaiyaoxinxi.shenpanliuchengbugongkaiyuanyin,f:anjiangaiyaoxinxi.shitima,f:anjiangaiyaoxinxi.buyigongkaishenpanliucheng,f:anjiangaiyaoxinxi.jingbanfayuan,f:anjiangaiyaoxinxi.lianbumenbiaozhi,f:anjiangaiyaoxinxi.shenpanliuchengyigongkai,f:anjiangaiyaoxinxi.anjianbiaozhi,f:anjiangaiyaoxinxi.anjianmingcheng,f:shitima,f:anjiangaiyaoxinxi.chengbanbumenbiaozhi'
) tblproperties ( 'hbase.table.name' = 'aj_15_baseinfo')

stored by 'org.apache.hadoop.hive.hbase.HBaseStorageHandler':底层数据在hbase中存储的话,需要指定该类进行处理。

with serdeproperties 中指定hbase中的字段与hive外部表的对应映射关系,其中::key为hbase的rowkey,其他字段按照外部表的定义顺序,依次以列族:字段名的顺序排列,用半角逗号分隔。

tblproperties 中指定对应的hbase表名。

需要注意的是:不要对该表进行复杂的条件查询,where中最好只使用rowkey对应的字段进行条件判断。

建议:只对该表进行数据的导出操作,即从hbase中把数据导出到hive实体表中。

2.Hive 访问MySQL

如同前面的描述,hive从 HIVE-1555 才开始支持自带的JdbcStorageHandler,在低版本的hive中要直接访问jdbc中的数据,只能通过第三方的JdbcStorageHandler实现。

第三方源码:https://github.com/qubole/Hive-JDBC-Storage-Handler

使用方式:

add jar /home/csc/20190729/qubole-hive-JDBC.jar;
add jar /home/csc/20190729/udf-1.0.jar;
use ods_sdb;
create external table if not exists ods_sdb.$v_table(
id string comment 'id',
fdm string comment '案件标识',
cBh string comment '当事人主键',
cCxm string comment '案件查询码',
nBgrpxh string comment '被告人排序号',
nFzje string comment '犯罪金额',
nSf string comment '特殊身份',
cSf string comment '特殊身份中文',
nZy string comment '职业',
cZy string comment '职业中文',
create_time string comment '创建时间'
) comment '当事人情况'
stored by 'org.apache.hadoop.hive.jdbc.storagehandler.JdbcStorageHandler'
tblproperties (
'mapred.jdbc.driver.class'='com.mysql.jdbc.Driver',
'mapred.jdbc.url'='jdbc:mysql://ip:port/fb_data?characterEncoding=utf8',
'mapred.jdbc.username'='username',
'mapred.jdbc.input.table.name'='fb_15_dsr',
'mapred.jdbc.password'='password',
'mapred.jdbc.hive.lazy.split'= 'false'
);

tblproperties中的各项配置,可以参考git上的描述。

问题定位解决:

(涉及到具体机器资源、环境,非重复复现的问题,修改方案,也只是临时性解决)

在实际使用过程中,处理当事人数据时,反复出现jdbc链接超时的情况,导致数据导出任务失败。

问题定位过程如下:

1.非标任务首次执行比较耗时,执行成功后,重跑速度相对较快;

2.show processlist;发现,在执行非标数据导出任务时,会优先执行一个count()的sql,比较耗时。分析非标数据在mysql中的存储,首先量级已达千万,其次,存储引擎采用的是InnoDB,对count()的执行需要遍历全表;

3.真正执行数据导出任务时,分为两个mapper执行select xxx的操作,时间消耗较少。

结合mysql的运行日志及数据导出任务的日志,基本定位到为count(*)导致的会话超时。

问题解决过程如下:

1.首先阅读JdbcStorageHandler的源码,定位count(*)的来源:

/*
* Copyright 2013-2015 Qubole
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/ package org.apache.hadoop.hive.wrapper; import java.io.IOException; import org.apache.hadoop.mapred.RecordReader;
import org.apache.hadoop.mapred.InputSplit;
import org.apache.hadoop.mapred.FileSplit;
import org.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapred.Reporter;
import org.apache.hadoop.mapreduce.lib.db.DBConfiguration; import org.apache.hadoop.mapreduce.InputFormat;
import org.apache.hadoop.mapreduce.TaskAttemptContext;
import org.apache.hadoop.mapreduce.TaskAttemptID;
import org.apache.hadoop.hive.shims.ShimLoader; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import java.sql.*;
import org.apache.hadoop.hive.jdbc.storagehandler.Constants;
import org.apache.hadoop.hive.jdbc.storagehandler.JdbcDBInputSplit;
public class RecordReaderWrapper<K, V> implements RecordReader<K, V> { private static final Log LOG = LogFactory.getLog(RecordReaderWrapper.class); private org.apache.hadoop.mapreduce.RecordReader<K, V> realReader;
private long splitLen; // for getPos() // expect readReader return same Key & Value objects (common case)
// this avoids extra serialization & deserialazion of these objects
private K keyObj = null;
protected V valueObj = null; private boolean firstRecord = false;
private boolean eof = false;
private Connection conn = null;
private String tblname = null;
private DBConfiguration delegate = null;
private long taskIdMapper = 0;
private boolean lazySplitActive = false;
private long count = 0;
private int chunks = 0;
public RecordReaderWrapper(InputFormat<K, V> newInputFormat,
InputSplit oldSplit, JobConf oldJobConf, Reporter reporter)
throws IOException { TaskAttemptID taskAttemptID = TaskAttemptID.forName(oldJobConf
.get("mapred.task.id")); if (taskAttemptID !=null) {
LOG.info("Task attempt id is >> " + taskAttemptID.toString());
} if(oldJobConf.get(Constants.LAZY_SPLIT) != null &&
(oldJobConf.get(Constants.LAZY_SPLIT)).toUpperCase().equals("TRUE")){
lazySplitActive = true;
ResultSet results = null;
Statement statement = null;
delegate = new DBConfiguration(oldJobConf);
try{
conn = delegate.getConnection(); statement = conn.createStatement();
results = statement.executeQuery("Select Count(*) from " + oldJobConf.get("mapred.jdbc.input.table.name"));
results.next(); count = results.getLong(1);
chunks = oldJobConf.getInt("mapred.map.tasks", 1);
LOG.info("Total numer of records: " + count + ". Total number of mappers: " + chunks );
splitLen = count/chunks;
if((count%chunks) != 0)
splitLen++;
LOG.info("Split Length is "+ splitLen);
results.close();
statement.close(); }
catch(Exception e){
// ignore Exception
}
}
org.apache.hadoop.mapreduce.InputSplit split; if(lazySplitActive){ ((JdbcDBInputSplit)(((InputSplitWrapper)oldSplit).realSplit)).setStart(splitLen);
((JdbcDBInputSplit)(((InputSplitWrapper)oldSplit).realSplit)).setEnd(splitLen);
} if (oldSplit.getClass() == FileSplit.class) {
split = new org.apache.hadoop.mapreduce.lib.input.FileSplit(
((FileSplit) oldSplit).getPath(),
((FileSplit) oldSplit).getStart(),
((FileSplit) oldSplit).getLength(), oldSplit.getLocations());
} else {
split = ((InputSplitWrapper) oldSplit).realSplit;
} // create a MapContext to pass reporter to record reader (for counters)
TaskAttemptContext taskContext = ShimLoader.getHadoopShims()
.newTaskAttemptContext(oldJobConf,
new ReporterWrapper(reporter)); try {
realReader = newInputFormat.createRecordReader(split, taskContext);
realReader.initialize(split, taskContext); // read once to gain access to key and value objects
if (realReader.nextKeyValue()) {
firstRecord = true;
keyObj = realReader.getCurrentKey();
valueObj = realReader.getCurrentValue();
} else {
eof = true;
}
} catch (InterruptedException e) {
throw new IOException(e);
}
}
}

results = statement.executeQuery("Select Count(*) from " + oldJobConf.get("mapred.jdbc.input.table.name"));

可以看到在执行数据导出任务前,首先会获取该表的总行数,用于进行任务的分割。但是,这里的触发条件是

'mapred.jdbc.hive.lazy.split'= 'true'

但是,该操作配置为false的情况下,仍然会默认执行count(*)的操作。

  1. 添加自定义表量级的阈值定义:
                count = oldJobConf.getInt("mapred.jdbc.input.table.count", 20000000);

//                results = statement.executeQuery("Select Count("+ (key==null?"*":key) + ") from " + oldJobConf.get("mapred.jdbc.input.table.name"));
// results.next(); // count = results.getLong(1);

3.外部表定义修改:

添加 'mapred.jdbc.input.table.count'='3000000'

4.重新打包,并上传;

5.问题搞定!

Hive直接读取Hbase及MySQL数据的更多相关文章

  1. Spark读取Hbase中的数据

    大家可能都知道很熟悉Spark的两种常见的数据读取方式(存放到RDD中):(1).调用parallelize函数直接从集合中获取数据,并存入RDD中:Java版本如下: JavaRDD<Inte ...

  2. hive和hbase本质区别——hbase本质是OLTP的nosql DB,而hive是OLAP 底层是hdfs,需从已有数据库同步数据到hdfs;hive可以用hbase中的数据,通过hive表映射到hbase表

    对于hbase当前noSql数据库的一种,最常见的应用场景就是采集的网页数据的存储,由于是key-value型数据库,可以再扩展到各种key-value应用场景,如日志信息的存储,对于内容信息不需要完 ...

  3. Spark 读取HBase和SolrCloud数据

    Spark1.6.2读取SolrCloud 5.5.1 //httpmime-4.4.1.jar // solr-solrj-5.5.1.jar //spark-solr-2.2.2-20161007 ...

  4. Hive综合HBase——经Hive阅读/书写 HBase桌子

    社论: 本文将Hive与HBase整合在一起,使Hive能够读取HBase中的数据,让Hadoop生态系统中最为经常使用的两大框架互相结合.相得益彰. watermark/2/text/aHR0cDo ...

  5. 使用Hive或Impala执行SQL语句,对存储在HBase中的数据操作

    CSSDesk body { background-color: #2574b0; } /*! zybuluo */ article,aside,details,figcaption,figure,f ...

  6. 使用Hive读取ElasticSearch中的数据

    本文将介绍如何通过Hive来读取ElasticSearch中的数据,然后我们可以像操作其他正常Hive表一样,使用Hive来直接操作ElasticSearch中的数据,将极大的方便开发人员.本文使用的 ...

  7. IDEA中Spark读Hbase中的数据

    import org.apache.hadoop.hbase.HBaseConfiguration import org.apache.hadoop.hbase.io.ImmutableBytesWr ...

  8. 关于mapreducer 读取hbase数据 存入mysql的实现过程

    mapreducer编程模型是一种八股文的代码逻辑,就以用户行为分析求流存率的作为例子 1.map端来说:必须继承hadoop规定好的mapper类:在读取hbase数据时,已经有现成的接口 Tabl ...

  9. 使用MapReduce读取HBase数据存储到MySQL

    Mapper读取HBase数据 package MapReduce; import org.apache.hadoop.hbase.Cell; import org.apache.hadoop.hba ...

随机推荐

  1. HZOJ string

    正解炸了…… 考试的时候想到了正解,非常高兴的打出来了线段树,又调了好长时间,对拍了一下发现除了非常大的点跑的有点慢外其他还行.因为复杂度算着有点高…… 最后正解死于常数太大……旁边的lyl用同样的算 ...

  2. Bert系列(二)——源码解读之模型主体

    本篇文章主要是解读模型主体代码modeling.py.在阅读这篇文章之前希望读者们对bert的相关理论有一定的了解,尤其是transformer的结构原理,网上的资料很多,本文内容对原理部分就不做过多 ...

  3. 用laravel搭一个微信公众号后台

    我使用的是laravel5.2, 早期版本可能不适合下面的方法. 在routes.php写下接收微信服务器post请求的路径: Route::post('wechatmp', 'WechatContr ...

  4. 第三期 第三期 搜索——1.运动规划(motion_planing)

    运动规划的根本问题在于机器人可能存在于一个这样的世界中, 它可能想找到一条到达这个目标的路径,那么就需要指定一个到达那里的计划, 自动驾驶汽车也会遇到这个问题.他可能处于高速公路的附近的街道网络中,他 ...

  5. spring mvc表单form值自动传到javabean-注解@ModelAttribute

    直接通过Form Bean进行表单可以简化表单提交的处理,特别是对于复杂表单,过于简单的表单就不建议了,因为毕竟需要额外创建一个Form Bean.前段时间项目中有一个比较复杂的表单,有多层次而且涉及 ...

  6. h5 的canvas绘制基本图形

    文章地址:https://www.cnblogs.com/sandraryan/ canvas是一个标签,可用于绘制复杂图形,渲染效果比普通DOM快 某些低版本浏览器不支持 canvas 使用原生几乎 ...

  7. HBuider快捷键

    朋友推荐用Hbuilder编辑器,看了下Hbuilder官网和那视频,感觉牛逼哄哄的, 自己也就体验了一下,打开Hbuilder的快捷键列表,每个快捷键都体验了一下,以下展示出来的,每一个都是精华,每 ...

  8. PHP 面试题三

    1.nginx使用哪种网络协议? nginx是应用层 我觉得从下往上的话 传输层用的是tcp/ip 应用层用的是http fastcgi负责调度进程 2. <? echo 'hello tush ...

  9. POJ 2763"Housewife Wind"(DFS序+树状数组+LCA)

    传送门 •题意 一对夫妇居住在 xx村庄,给村庄有 $n$ 个小屋: 这 $n$ 个小屋之间有双向可达的道路,不会出现环,即所构成的图是个树: 从 $a_i$ 小屋到 $b_i$ 小屋需要花费 $w_ ...

  10. svn 冲突解决办法(黄色感叹号)

    右键:"TortoiseSVN"->"Resolved..."已解决的..., 选中全部的文件,然后OK,,然后就可以commit提交了.