欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Hive简介及使用

程序员文章站 2022-04-29 20:58:36
...

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的系统架构

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=JAVAHOME/bin:JAVA_HOME/bin:PATH:HADOOPHOME/bin:HADOOP_HOME/bin: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));
        }
 }
}