Hive简介及使用
Hive的简介
- Hive 是建立在 Hadoop 上的数据仓库基础构架。它提供了一系列的工具,可以用来进行数据提取转化加载(ETL ),这是一种可以存储、查询和分析存储在 Hadoop 中的大规模数据的机制。Hive 定义了简单的类 SQL 查询语言,它允许熟悉 SQL 的用户查询数据。同时,这个语言也允许熟悉 MapReduce 开发者的开发自定义的 mapper 和 reducer 来处理内建的 mapper 和 reducer 无法完成的复杂的分析工作;
- Hive是SQL解析引擎,它将SQL语句转译成M/R Job然后在Hadoop执行;
- Hive的表其实就是HDFS的目录/文件,按表名把文件夹分开。如果是分区表,则分区值是子文件夹,可以直接在M/R Job里使用这些数据。
Hive的系统架构
用户接口主要有三个:CLI,JDBC/ODBC和 WebUI
- CLI,即Shell命令行;
- DBC/ODBC 是 Hive 的Java,与使用传统数据库JDBC的方式类似;
- WebGUI是通过浏览器访问 Hive;
- Hive 将元数据存储在数据库中(metastore),目前只支持 mysql、derby,Hive 中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等;
- 解释器、编译器、优化器完成 HQL 查询语句从词法分析、语法分析、编译、优化以及查询计划(plan)的生成。生成的查询计划存储在 HDFS 中,并在随后有 MapReduce 调用执行;
- Hive 的数据存储在 HDFS 中,大部分的查询由 MapReduce 完成(包含 * 的查询,比如 select * from table 不会生成 MapRedcue 任务)。
Hive的安装配置
安装
解压下载的hive包,然后配置环境变量
修改/etc/profile文件。
export HIVE_HOME=/usr/local/hive
export PATH=PATH:HIVE_HOME/bin
启动hive:cd/hive/bin ./hive
metastore 元数据信息
默认以derby数据库作为保存hive的元数据信息,缺点:只支持一个链接
以mysql数据库作为保存hive的元数据信息
配置hive
cp hive-default.xml.template hive-site.xml
修改hive-site.xml(删除所有内容,只留一个)
添加如下内容:
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://hadoop01:3306/metastore?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</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>hadoop</value>
<description>password to use against metastore database</description>
</property>
安装hive和mysq完成后,将mysql的连接jar包拷贝到$HIVE_HOME/lib目录下
如果出现没有权限的问题,在mysql授权(在安装mysql的机器上执行)
mysql -uroot -p
#(执行下面的语句 .:所有库下的所有表 %:任何IP地址或主机都可以连接)
GRANT ALL PRIVILEGES ON . TO ‘root’@’%’ IDENTIFIED BY ‘hadoop’ WITH GRANT OPTION;
FLUSH PRIVILEGES;
Hive的启动方式
- hive 命令行模式,直接输入#/hive/bin/hive的执行程序,或者输入 #hive --service cli
- hive web界面的 (端口号9999) 启动方式,#hive --service hwi &,用于通过浏览器来访问hivehttp://hadoop01:9999/hwi/
- hive 远程服务 (端口号10000) 启动方式(java api远程连接必须启动)
#hive --service hiveserver &
Hive的数据
数据类型
- 基本数据类型:tinyint/smallint/int/bigint; float/double;boolean;string
- 复杂数据类型:Array/Map/Struct
- 没有date/datetime
数据存储
- Hive的数据存储基于Hadoop HDFS
- Hive没有专门的数据存储格式
- 存储结构主要包括:数据库、文件、表、视图
- Hive默认可以直接加载文本文件(TextFile),还支持sequence file 、RC file
创建表时,指定Hive数据的列分隔符与行分隔符,Hive即可解析数据
Hive与传统数据库的比较
查询语言 | HiveQL | SQL |
---|---|---|
数据存储位置 | HDFS | RawDevice or 本地FS |
数据格式 | 用户定义 | 系统决定 |
数据更新 | 不支持 | 支持 |
执行 | MapReduce | Executor |
执行延迟 | 高 | 低 |
可扩展性 | 高 | 低 |
数据规模 | 大 | 小 |
Hive的相关操作
-
创建库,类似传统数据库的DataBase,默认数据库"default"使用#hive命令后,不使用hive>use <数据库名>,系统默认的数据库。可以显式使用hive> use default;创建一个新库:hive > create database hive;
-
创建表(指定分隔符):create table user_info (id bigint, account string, name string, age int) row format delimited fields terminated by ‘\t’;
-
从本地文件系统load文件:load data local inpath ‘/home/userinfo’ into table user_info;覆盖null行,insert overwrite table student select * from student where id is not null;
-
创建外部表:先有数据,后创建表指向HDFS文件的表,默认是MANAGED_TABLE管理的表(表示先创建表,后添加数据),HIVE shell 下运行hdfs: dfs 命令:create external table ext_student(id bigint, name string,age int) row format delimited fields terminated by ‘\t’ location ‘/hivedata’;
-
创建分区表:普通表和分区表区别:有大量数据增加的需要建分区表;create external table students(id bigint, name string,age int) partitioned by (nation string) row format delimited fields terminated by ‘\t’ location ‘/hivedata’;分区是子文件夹,分区加载数据,load data local inpath ‘/home/students_c’ into table students partition (nation=‘china’);分区查询:select * from students where nation=‘china’;
-
将数据库中的数据导入到HIVE中,并进行计算:在hive当中创建两张表
create table trade_detail (id int, account string, income double, expenses double, time string) row format delimited fields terminated by ‘\t’;
create table user_info (id int, account string, name string, age int) row format delimited fields terminated by ‘\t’;
将mysq当中的数据直接导入到hive当中;sqoop import --connect jdbc:mysql://192.168.1.101:3306/demo --username root --password hadoop --table trade_detail --hive-import --hive-overwrite --hive-table trade_detail --fields-terminated-by ‘\t’;sqoop import --connect jdbc:mysql://192.168.1.10:3306/itcast --username root --password 123 --table user_info --hive-import --hive-overwrite --hive-table user_info --fields-terminated-by ‘\t’;
创建一个result表保存前一个sql执行的结果;create table result row format delimited fields terminated by ‘\t’ as select t2.account, t2.name, t1.income, t1.expenses, t1.surplus from user_info t2 join (select account, sum(income) as income, sum(expense) as expenses, sum(income-expense) as surplus from trade_detail group by account) t1 on (t1.account = t2.account); -
Hive的UDF(自定义函数)
package cn.com.hive.demo;
import java.util.HashMap;
import java.util.Map;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;
public class HiveUDF extends UDF{
static Map<String,String> nationMap = new HashMap<String,String>();
static {
nationMap.put("china","中国");
nationMap.put("japan","日本");
}
public Text evaluate(String nation){
Text text = new Text();
String str = nationMap.get(nation);
text.set(str);
return text;
}
}
打包成jar包,并上传到linux环境;
hive中自定义函数调用过程:
1.添加jar包(在hive命令行里面执行)
hive> add jar /root/UDF.jar;
2.创建临时函数
hive> create temporary function getNation as 'package cn.com.hive.demo.HiveUDF‘ ;
3.调用
hive> select id, name, getNation(nation) from student;
- hive的api 操作
public class HiveApiTest {
private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";
private static String url = "jdbc:hive://hadoop02:10000/default";
private static String user = "root";
private static String password = "hadoop";
public static void main(String[] args) {
Connection conn = null;
try {
conn = getConn();
System.out.println(conn );
Statement stmt = conn.createStatement();
//createtable();//创建hellohive表
//desctable(); //查看表结构
//loadData(stmt,"hellohive");//向表中查入数据
selecttable(stmt,"hellohive");//查询表中的数据
} catch (Exception e) {
e.printStackTrace();
}
}
//建立连接
private static Connection getConn() throws ClassNotFoundException,SQLException {
Class.forName(driverName);
Connection conn = DriverManager.getConnection(url, user, password);
return conn;
}
//创建表以及删除表
private static void createtable(){
try {
Connection conn =getConn();
Statement stmt = conn.createStatement();
String tableName = "hellohive";
stmt.execute("drop table if exists " + tableName);
stmt.execute("create table "+tableName+" (key int, value string) row format delimited fields terminated by '\t'");
System.out.println("Create table success!");
} catch (Exception e) {
e.printStackTrace();
}
}
//查看表结构
private static void desctable(){
try {
Connection conn =getConn();
Statement stmt = conn.createStatement();
String tableName = "hellohive";
String sql = "describe " + tableName;
System.out.println("Running: " + sql);
ResultSet res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(res.getString(1) + "\t" + res.getString(2));
}
} catch (ClassNotFoundException | SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void loadData(Statement stmt, String tableName)throws SQLException {
String filepath = "/home/hadoop/hello.txt";
String sql = "load data local inpath '" + filepath + "' into table "
+ tableName;
System.out.println("Running:" + sql);
stmt.execute(sql);
}
private static void selecttable(Statement stmt, String tableName) throws SQLException{
String sql = "select * from " + tableName;
ResultSet res = stmt.executeQuery(sql);
while (res.next()) {
System.out.println(String.valueOf(res.getInt(1)) + "\t"
+ res.getString(2));
}
}
}
上一篇: 干货|Linux平台搭建网关服务器