Hive动手实践

一 Hive是什么?为什么会出现?解决了什么问题?

Hive它不是一个数据库,它是一个数据仓库。它只是提供了我们通过类SQL语句访问存储在HDFS上的数据的一个接口。它借用了HDFS的可拓展、高可用、海量数据存储的优势(真正的数据存储在HDFS上),同时借用MapReduce计算框架的计算功能,并将HDFS上文件和Hive表的映射关系存储在关系型数据库中。通过解析类SQL语句和XML驱动的方式,调用内置的MapReduce程序去执行(可编程自定义),并将结果返回。
一个叫facebook的贼有名的公司,他们内部搭建了数据仓库(你可以理解成把一大堆数据放到一个地方,然后做报表给老板看!),是基于关系型数据库的。后来随着数据量的不断增加,这种传统的数据库扛不住了。于是经过一系列的折腾换到了hadoop上。问题来了!以前基于数据库的数据仓库用sql就能做查询,现在换到hdfs上面,得跑Mapreduce任务去做分析,这样以前做分析的人还得学mapreduce,这只适用于有经验的java开发人员。于是,他们就开发了一套框架就是用sql来做hdfs的查询(用户输入的是sql,框架内部把sql转成mapreduce的任务,然后再去跑分析)。
Hive基于类似SQL的语言完成对hdfs数据的查询分析。1、它支持各种命令,比如dfs的命令、脚本的执行。2、 如果你输入的是sql,它会交给一个叫做Driver的东东,去编译解析。3 、把编译出来的东西交给hadoop去跑...然后返回查询结果。这让只有数据库分析能力而不具备开发能力的工程师的工作能力得以保存下来,节省了公司的成本,减少了系统的复杂程度。

二 如何搭建?

下载解压以及环境变量的配置
前提:搭建好hadoop集群,hive可以放在任何一台机器,只要该台机器能够连接HDFS。
hive安装包 ,选择一个合适的版本进行下载。
解压该数据包:
tar -xzf apache-hive-2.1.1-bin.tar.gz
该名字太长我们可以建立一个软链:
ln -sf ./apache-hive-2.1.1-bin ./hive
配置环境变量:进/home下
 sudo vim .bashrc

ESC+wq保存退出

安装关系型数据库mysql(内置的数据库非常不稳定)
sudo apt-get install mysql-server
可能需要输入密码,记住该密码连数据库的时候要用到。查看mysql数据安装是否成功:sudo netstat -tap | grep mysql,如果能看到mysql监听端口则代表安装成功。例如:
由上面图片可知,mysql server监听的是本地发来的请求,如果是任意主机都可以请求,则写为0.0.0.0,但是这样又不太安全。监听某ip,指定此ip地址即可,但是要保证mysql的user中有允许此ip访问,否则不能对数据库操作。如果不选择修改配置文件,则hive连接时设置的主机地址为localhost。
如没有成功则用service mysqld start 启动mysql。netstat -nptl | grep 3306 查看3306端口监听情况(3306端口为默认JDBC连接mysql数据库端口)。
连接mysql需要连接驱动(mysql-connector-java-5.1.42-bin.jar) 放到hive的lib目录中去: 下载地址 选择合适版本,放到hive下的lib目录下。

登陆到mysql:
mysql -u root -p   //(用默认密码或者设置的密码abc123)
授权grant(该命令非常强大,可自行学习):
grant all on *.* to root@'%' identified by 'abc123'
该命令的作用,就是给任何IP地址以root身份以密码abc123访问mysql数据库任何表的权限。
创建hive数据库(hive待会就连该数据库):
create database hive;

修改Hive配置文件
修改hive-site.xml(由hive/conf目录下的临时文件改名而来):
cp hive-default.xml.template hive-site.xml
配置连接关系型数据库:
  <property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://localhost/hive</value>
  </property>
连接数据库驱动:
  <property>
    <name>javax.jdo.option.ConnectionDriverName</name>
    <value>com.mysql.jdbc.Driver</value>
    <description>Driver class name for a JDBC metastore</description>
  </property>
连接用户名:
<property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>root</value>
    <description>Username to use against metastore database</description>
  </property>
连接数据库密码:
  <property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>abc123</value>
    <description>password to use against metastore database</description>
  </property>
修改所有的system.io.tmpdir为指定的目录(自己定,我放在/usr/hive/tmp下了)

修改好hive连接mysql的一些配置文件之后,就可以启动hive了 hive会根据配置文件自动的去连接好mysql数据库。这个时候hive中是没有数据表的,但mysql中会有很多初始化表。因为mysql存储的是映射文件。hive是将类sql脚本转化为mapreduce去执行,因此需要这些与hdfs上的文件的映射关系。
初始化schema
由于Hive中所有的原信息都需要存储到关系型数据库里面,因此需要初始化数据库表。
schematool -dbType mysql -initSchema
启动hive cli测试
接下来如果你配好了环境变量和PATH路径,就可以直接键入hive,启动它了。(先启动hadoop,这里你可能会有一个问题,我并没有配hadoop的任何东西,它如何将数据存储至HDFS,那是因为它会根据环境变量以及hadoop的配置找到HDFS的入口)。
xiao@node1:~/hive/conf$ hive
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/home/xiao/apache-hive-2.1.1-bin/lib/log4j-slf4j-impl-2.4.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/usr/soft/hadoop-2.7.3/share/hadoop/common/lib/slf4j-log4j12-1.7.10.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]
Hive-on-MR is deprecated in Hive 2 and may not be available in the future versions. Consider using a different execution engine (i.e. spark, tez) or using Hive 1.X releases.
hive> show tables;
OK
test1
test3
Time taken: 1.552 seconds, Fetched: 2 row(s)
hive> 

第三 如何使用?

首先介绍CLI命令,在linux shell下:
xiao@node1:~/hive/conf$ hive -help
 -d,--define <key=value>          Variable subsitution to apply to hive
                                  commands. e.g. -d A=B or --define A=B
    --database <databasename>     Specify the database to use
 -e <quoted-query-string>         SQL from command line
 -f <filename>                    SQL from files
 -H,--help                        Print help information
    --hiveconf <property=value>   Use value for given property
    --hivevar <key=value>         Variable subsitution to apply to hive
                                  commands. e.g. --hivevar A=B
 -i <filename>                    Initialization SQL file
 -S,--silent                      Silent mode in interactive shell
 -v,--verbose                     Verbose mode (echo executed SQL to the
                                  console
介绍几个重要的:
hive -e "sql语句" 执行一条sql
例:
xiao@node1:~/hive/conf$ hive -e "show tables"
hive -f "运行文件名" 执行一系列sql
例:
xiao@node1:~/hive/conf$ hive -f "./test.sql"
hive -i 文件名 初始化hive

接下来介绍一下一些与关系型数据库不同的创建数据库命令:
创建表 :
create table t_emp(
id int,
name string,
age int,
dept_name  string
)
row format delimited 
fields  terminated by ',';
后面接的这一句的意思是数据每一行的数据都后“,”隔开。例如:
001,张三,20
002,王五,25
003,赵六,36
数据的导入导出:
第一种方式,直接从本地文件系统导入数据
我的本机有一个test1.txt文件,这个文件中有三列数据,并且每列都是以','为分隔
[root@localhost conf]# cat /usr/tmp/test1.txt1 
001,张三,20
002,王五,25
003,赵六,36
创建数据表:
hive>create table test1(a string,b string,c string)hive>row format delimitedhive>fields terminated by ','hive>stored as textfile;
导入数据:
load data local inpath '/usr/tmp/test1.txt' overwrite into table test1;
其中local inpath,表明路径为本机路径,overwrite表示加载的数据会覆盖原来的内容
第二种,从hdfs文件中导入数据
首先上传数据到hdfs中
hadoop fs -put /usr/tmp/test1.txt /test1.txt
在hive中查看test1.txt文件
hive> dfs -cat /test1.txt;
001,张三,20
002,王五,25
003,赵六,36
创建数据表,与前面一样。导入数据的命令有些差异:
load data inpath '/test1.txt' overwrite into table test2;
第三种,基于查询insert into导入
首先定义数据表,这里直接创建带有分区的表
hive> create table test3(a string,b string,c string) partitioned by (d string) row format delimited fields 
terminated by ',' stored as textfile;
OKTime taken: 0.109 seconds
hive> describe test3;OK
a                       string 
b                       string
c                       string 
d                       string 
# Partition Information      # col_name              data_type      comment         d              string 
Time taken: 0.071 seconds, Fetched: 9 row(s)
这里有个分区的概念,后面会解释。
通过查询直接导入数据到固定的分区表中:
hive> insert into table test3 partition(d='aaaaaa') select * from test2;
Query ID = root_20160823212718_9cfdbea4-42fa-4267-ac46-9ac2c357f944Total jobs = 3Launching Job 1 out of 
3Number of reduce tasks is set to 0 since there's no reduce operatorJob running in-process (local Hadoop)
2016-08-23 21:27:21,621 Stage-1 map = 100%, reduce = 0%Ended Job = job_local1550375778_0001Stage-4 is selected
 by condition resolver.Stage-3 is filtered out by condition resolver.Stage-5 is filtered out by condition 
resolver.Moving data to directory hdfs://localhost:8020/user/hive/warehouse/test.db/test3/d=aaaaaa/
.hive-staging_hive_2016-08-23_21-27-18_739_4058721562930266873-1/-ext-10000Loading data to table test.test3 partition
(d=aaaaaa)MapReduce Jobs Launched: Stage-Stage-1:  HDFS Read: 248 HDFS Write: 175 SUCCESSTotal
MapReduce CPU Time Spent: 0 msecOKTime taken: 3.647 seconds
通过查询观察结果
hive> select * from test3;
001,张三,20
002,王五,25
003,赵六,36
Fetched: 4 row(s)
直接通过查询创建数据表:
hive> create table test5 as select * from test4;
Query ID = root_20160823213944_03672168-bc56-43d7-aefb-cac03a6558bfTotal jobs = 3Launching Job 1 out of 3Number 
of reduce tasks is set to 0 since there's no reduce operatorJob running in-process (local Hadoop)2016-08-23 21:39:46,
030 Stage-1 map = 100%,  reduce = 0%Ended Job = job_local855333165_0003Stage-4 is selected by condition resolver.Stage-3
 is filtered out by condition resolver.Stage-5 is filtered out by condition resolver.Moving data to directory 
hdfs://localhost:8020/user/hive/warehouse/test.db/.hive-staging_hive_2016-08-23_21-39-44_259_5484795730585321098-1/-
ext-10002Moving data to directory hdfs://localhost:8020/user/hive/warehouse/test.db/test5MapReduce Jobs Launched: Stage-
Stage-1:  HDFS Read: 600 HDFS Write: 466 SUCCESSTotal MapReduce CPU Time Spent: 0 msecOKTime taken: 2.184 seconds
查看结果:
hive> select * from test5;
001,张三,20
002,王五,25
003,赵六,36
Fetched: 4 row(s)
导出数据
导出到本地文件
执行导出本地文件命令:
hive> insert overwrite local directory '/usr/tmp/export' select * from test1;
Query ID = root_20160823221655_05b05863-6273-4bdd-aad2-e80d4982425dTotal jobs = 1Launching Job 1 out of 1Number 
of reduce tasks is set to 0 since there's no reduce operatorJob running in-process (local Hadoop)2016-08-23 22:16:57,028
 Stage-1 map = 100%,  reduce = 0%Ended Job = job_local8632460_0005Moving data to local directory /usr/tmp/exportMapReduce
 Jobs Launched: Stage-Stage-1:  HDFS Read: 794 HDFS Write: 498 SUCCESSTotal MapReduce CPU Time Spent: 0 msecOKTime taken: 
1.569 secondshive>
在本地文件查看内容
导出到hdfs
hive> insert overwrite directory '/usr/tmp/test' select * from test1;
导出成功,查看导出的hdfs文件。
此外还可以通过:
export table t_emp to '/usr/input/emp.txt';  // 命令导出数据至HDFS上
创建分区表:(show partitions)
在创建表的时候,我们可以指定一个字段作为分区。在我们查询表结构的时候会出现该字段,但它并不是表的一部分,在HDFS中它以表名下的一个目录名出现。在导入数据时,我们需要显示的指定分区(如下面的例子)。它的作用就是,在HDFS上多建立了一级目录,以此来减少查询数据时的扫描范围,提高速度。分区表实际上是一个文件夹,分区可以根据时间地点等等进行划分。它会为数据提供额外的结构以获得更高效的查询处理。在文件系统级别,分区只是表目录下嵌套的子目录。
create table logs (ts bigint,line String)Partirion by(dt String,country=‘GB’);
load data local inpath ‘/root/data.txt’ into table logs partition(dt=‘2001-01-01’,county=‘GB’);
记住,partition by 子句中的列定义是表中正式的列,称为“分区列”,但是,数据文件并不包含这些列的值,因为它们源于目录。在查找时,可以使用where关键字对输入进行修剪,从而只扫描相关的分区。
insert into table dept_count partition (dname=‘销售部’)select count(1) from t_emp
where dept_name=‘销售部’ group by dept_name;
四 其他
前面我们介绍了hive的安装到使用一条龙服务。但在实际的工程中,我们很少会在hive命令行下去执行HQL或进行数据的导入导出,它仅仅是在调试的时候用的比较多。常见的方式是:
通过java编码的方式来执行hql脚本。借助Eclipse编码,同时需要解压hive找到其中的一个jar包导入项目中去。lib目录下的jar包。本质也是登入hive中去执行。
代码:
1.获得关系型数据库来使用(当成关系型数据库)
2.hive本身不是一个服务,因此通过jdbc去连数据库连接不上。我们需要将hive变成一个服务。./hive --service hiveserver2 默认是localhost:10000端口在监听,这个时候外界是连不上的,我们需要将localhost改成主机地址或ip地址。
3.可以通过hive/bin的。/beeline命令去测试能否连该服务。例:
!connect jdbc:hive2://node1:10000/default 
4.修改配置文件中的5000L为5000.
编码:
Class.forname("org.apache.hive.jdbc.hiveDriver");
Connection conn=DriverManager.getConnection("jdbc:hive2://node1/default","root","");
具体的可深入学习,这里算是开个头。
同时在我们执行HQL的时候,我们可以直接调用sql 的一些函数,如sum()、count()等函数。但在实际的工程中,这些函数远远不够我们使用,这个时候我们可以自己编写函数。
hive 有两种函数:UDF,UDAF
1.UDF:表示输入数据为一条数据,输出数据也为一条数据 UDF必须使用java编写。
一个UDF必须满足下面两个条件:
一个UDF必须是org.apace.hadoop.hive.ql.exec.UDF的子类
一个UDF必须至少实现了evaluate()方法
为了在Hive中使用UDF,我们需要将编译后的java类打包成jar文件,并在HIve中注册这个为文件 add jar /path/to/hive-example.jar
同时还需要给JAVA的类名起一个别名
create temporary function strip AS ‘com.hadoop.hive.Strip’
这里的意思是只为这个hive会话过程定义。意味着每次运行hive脚本都必须添加jar文件或者定义函数。或者在主目录创建包含这些命令的.hiverc文件,以使得这些UDF会在每个HIve会话开始的时候运行。还可以在Hive启动的时候指定查找附加的jar文件的路径。
2.UDAF:输入数据为多行数据,并产生一个数据行。Count聚合函数等。

Hive作为大数据环境下的数据仓库工具,支持基于hadoop以sql的方式执行mapreduce的任务,非常适合对大量的数据进行全量的查询分析。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值