大数据学习之Hive学习

hive

Hadoop的MapReduce在海量数据离线处理中遇到的问题

  1. MR程序代码量较大,开发调试复杂,不适合要求快速得出结果的工作场景.
  2. Hadoop是用Java开发,MR天生对Java支持最好的,对于其他语言的使用者,不够友好.
  3. 想要编写一个优秀的MR程序,必须掌握Hadoop的一些底层原理.API冗长繁琐不好记忆.

概念:

Hive是一个基于Hadoop的数据仓库工具(本质是Hadoop的一个客户端),他的出现避免了传统MR开发的弊病,允许开发者使用简单的SQL来实现海量数据的离线处理,并且内置了非常丰富的函数库供开发者直接调用,同时在内置函数不够用的时候还支持UDF(用户自定义函数)

面向仓库

数据仓库是一个面向主题的稳定的,继承的反应历史数据的数据存储系统,一般用于为管理者提供决策分析的数据支持。

安装Hive

hive上传和解压
复制conf文件下的hive-default.xml.template为hive-site.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
  <property>
  <name>hive.default.fileformat</name>
  <value>TextFile</value>
</property>
<property>
  <!--端口改为你自己的端口,这里是连接数据库中hive数据库-->
  <name>javax.jdo.option.ConnectionURL</name>
  <value>jdbc:mysql://hadoop01:3306/hive?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>
  <!--连接MySQL的用户名-->
  <name>javax.jdo.option.ConnectionUserName</name>
  <value>root</value>
  <description>username to use against metastore database</description>
</property>
<property>
  <!--连接MySQL的密码-->
  <name>javax.jdo.option.ConnectionPassword</name>
  <value>root</value>
  <description>password to use against metastore database</description>
</property>
</configuration>

上传mysql的驱动jar包(官网下载)

# 进入mysql
mysql
# 进入mysql客户端(命令行)执行
grant all privileges on *.* to 'root'@'hadoop01' identified by 'root' with grant option;
 
flush privileges;
# 初始化
schematool -dbType mysql -initSchema

如果出现错误:

grant all privileges on *.* to 'root'@'hadoop01' identified by 'root' with grant option;
 
flush privileges;

启动

在/home/app/apache-hive-2.3.6-bin/bin目录下执行

./hive

测试案例

新建数据库
create database test;
查询数据库
show databases;
新建表 (注意 :hive是基于Java开发的,所以字段的属性都是Java的定义类型)
create table tb_user(id int,name string ,age int);
插入数据
insert into tb_user(1,"3",3);
查询数据
select * from tb_user;

其他操作

将本地文件添加到数据库

# 创建表选择分割方式(以"\t"为例  \t是代表分割符)
create table tb_book1 (id int,name string) row format delimited fields terminated by "\t";

# 插入文件
load data local inpath '/home/data/book1.txt' into table tb_book1;

外部表(EXTERNAL_TABLE)

先准备数据,然后将不熬结构投影在准备好的数据之上形成表的形式

create external table tb_name(属性1,属性2) row format delimited fields terminated by "分割符" location "位置";

分区表

是hive实现面向主题的方式(分区不是越多越好)
分区表的建立

create table tb_par(建表属性) partitioned by (分区属性) row format delimited fields terminated by "\t";

例子

create table tb_par(id int,name string) partitioned by (country string) row format delimited fields terminated by "\t";

插入数据

load data local inpath "文件位置" into table tb_par partition (分区信息);

例子

load data local inpath "/home/data/CHN.txt" into table tb_par partition (country="CHN");
load data local inpath '/home/data/JPA_female.txt' overwrite into table tb_par2 partition (country='JPA',gender='female');

追加数据

 alter table tb_par add partition ( country = "JPN" ) location "/user/hive/warehouse/jt.db/tb_par/JPN.txt";

分桶表

用于解决在测试环节全量数据参与运算太慢,但随意的抽取部分数据又不具有代表性的问题
建表

create table tb_data (id int,name string) row format delimited fields terminated by ",";
--插入数据
load data local inpath '/home/data/teachers.txt' into table tb_data;

创建分桶的表

--创建桶表
create table tb_name (属性1,属性2.... ) clustered by (属性) into y bucket
--开启分批次 
set hive.enforce.bucketing=true;
--插入数据
insert into table tb_name select * from tb_data;
--查询数据
select * from tb_name;
--分桶查询(x代表第几桶,y代表共几桶,x<y)
select * from tb_name tablesample (bucket x out of y on id);

例子

--创建桶表
create table tb_buc (id int,name string ) clustered by (id ) into 4 bucket
--开启分批次 
set hive.enforce.bucketing=true;
--插入数据
insert into table tb_buc select * from tb_data;
--查询数据
select * from tb_buc;
--分桶查询(按桶进行数据取样)
select * from tb_buc tablesample (bucket 4 out of 4 on id);
--分桶查询(按比例	进行数据取样)
select * from table_name tablesample(30 percent);

进阶:hivejdbc

在Hadoop配置文件中加入以下内容
hdfs-site.xml

<property>  
<name>dfs.webhdfs.enabled</name>  
<value>true</value>  
</property>  
core-site.xml

<property>
<name>hadoop.proxyuser.root.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.root.groups</name>
<value>*</value>
</property>

启动hiveserver2
在hive安装目录下的bin目录中执行
./hiveserver2
pom

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>cn.tedu</groupId>
    <artifactId>flume</artifactId>
    <version>1.0-SNAPSHOT</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.apache.hive</groupId>
            <artifactId>hive-jdbc</artifactId>
            <version>2.3.6</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.14</version>
        </dependency>
 
    </dependencies>
</project>

代码

package cn.tedu.flume;

import java.sql.*;

public class HiveJDBC {
   private static String driverName = "org.apache.hive.jdbc.HiveDriver";

   /**
    * @param args
    * @throws SQLException
    */
   public static void main(String[] args) throws SQLException {
       try {
           Class.forName(driverName);
       } catch (ClassNotFoundException e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
           System.exit(1);
       }
       Connection con = DriverManager.getConnection("jdbc:hive2://hadoop01:10000/default", "root", "");
       Statement stmt = con.createStatement();
       String dbName = "test";
       String tableName = dbName+".tb_test";
       System.out.println("insert into table "+ tableName + " values(1, 'dongcc')");
       stmt.execute("drop database if exists " + dbName);
       stmt.execute("create database " + dbName);
       stmt.execute("drop table if exists " + tableName);
       stmt.execute("create table " + tableName + " (key int, value string)");
       stmt.execute("insert into table " + tableName + " values(1, 'dongcc')");
       // show tables
       String sql = "select * from "+tableName;
       System.out.println("Running: " + sql);
       ResultSet res = stmt.executeQuery(sql);
       if (res.next()) {
           System.out.println(res.getString(1));
           System.out.println(res.getString(2));
       }
   }
}

补充
数据仓库和关系型数据库的区别:

数据库数据仓库
面向事务面向主题
实时数据历史数据
避免冗余有意冗余
捕获数据分析数据
为用户提供服务为管理者提供服务

所有的离线数据处理场景都适用hive吗?

并不是所有场景都适合,逻辑简单又要求快速出结果的场景Hive优势更大。但是在业务逻辑非常复杂的情况下还是需要开发MapReduce程序更加直接有效。

Hive能作为业务系统的数据库使用吗?

不能。传统数据库要求能够为系统提供实时的增删改查,而Hive不支持行级别的增删改,查询的速度也不比传统关系型数据库,而是胜在吞吐量高,所以不能作为关系型数据库来使用。

Hive与传统MR方式处理数据相比能够提高运行效率吗?能够提高工作效率吗?

Hive的使用中需要将HQL编译为MR来运行,所以在执行效率上要低于直接运行MR程序。但是对于我们来说,由于只需要编写调试HQL,而不用开发调试复杂的MR程序,所以工作效率能够大大提高。

Hive为什么不支持行级别的增删改?

Hive不支持行级别的增删改的根本原因在于他的底层HDFS本身不支持。在HDFS中如果对整个文件的某一段或某一行内容进行增删改,势必会影响整个文件在集群中的存放布局。需要对整个集群中的数据进行汇总,重新切块,重新发送数据到每个节点,并备份,这样的情况是得不偿失的。所以HDFS的设计模式使他天生不适合做这个事
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值