Live2D

Hive的学习

1.Hive的安装

1.下载hive安装包
wget  --no-check-certificate  https://dlcdn.apache.org/hive/hive-3.1.2/apache-hive-3.1.2-bin.tar.gz
2.解压
tar -zxvf apache-hive-3.1.2-bin.tar.gz
3.配置环境变量
vim /etc/profile

添加以下内容

#hive


export HIVE_HOME=/home/wl/apache-hive-3.1.2-bin

export PATH=$PATH:$HIVE_HOME/bin

image

让配置文件生效

source /etc/profile
4.初始化元数据库

来到安装目录 /home/wl/apache-hive-3.1.2-bin,输入以下指令初始化元数据库

bin/schematool -dbType derby -initSchema

2.安装mysql

1.查看当前系统是否安装过mysql
rpm -qa|grep mariadb

如过有,执行以下命令卸载

rpm -e --nodeps mariadb-libs

image

2.下载安装mysql

执行以下命令下载mysql安装包

wget https://cdn.mysql.com//Downloads/MySQL-5.7/mysql-5.7.36-1.el7.x86_64.rpm-bundle.tar

下载完成后,解压

tar -xf mysql-5.7.36-1.el7.x86_64.rpm-bundle.tar

image

然后依次解压以下几个rpm包

rpm -ivh mysql-community-common-5.7.36-1.el7.x86_64.rpm

rpm -ivh mysql-community-libs-5.7.36-1.el7.x86_64.rpm

rpm -ivh mysql-community-libs-compat-5.7.36-1.el7.x86_64.rpm

rpm -ivh mysql-community-client-5.7.36-1.el7.x86_64.rpm

rpm -ivh mysql-community-server-5.7.36-1.el7.x86_64.rpm
3.删除旧数据

如果/etc/my.cnf里面的datadir 指向的目录下的有内容就删掉

查看/etc/my.cnf里面的内容

image

找到 /var/lib/mysql 目录,ls查看,如果有内容 就删除掉

image

4.初始化数据库

初始化数据库

sudo mysqld --initialize --user=mysql

查看临时生成的root用户的密码

cat /var/log/mysqld.log

image

启动mysql

systemctl start mysqld

进入mysql中

mysql -u root -p

修改root用户的密码

mysql> set password = password("新密码");

修改 mysql 库下的 user 表中的 root 用户允许任意 ip 连接

说明:这样做的好处就是,navicat这些可视化工具可以连接了

update mysql.user set host='%' where user='root';


flush privileges;
5.下载mysql连接驱动包

下载

wget https://cdn.mysql.com/archives/mysql-connector-java-5.1/mysql-connector-java-5.1.47.tar.gz

解压

tar -zxvf mysql-connector-java-5.1.47.tar.gz

进入到目录里面找到 mysql-connector-java-5.1.47.jar,将其移动到hivelib目录下

mv mysql-connector-java-5.1.47.jar  /home/wl/apache-hive-3.1.2-bin/lib/

3.配置Metastore到mysql

1.新增配置文件

在hive的conf目录下新建hive-site.xml,添加以下内容

<?xml version="1.0"?>


<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>

<!-- jdbc 连接的 URL --> 

  <property>

       <name>javax.jdo.option.ConnectionURL</name>

       <value>jdbc:mysql://wlwl:3306/metastore?useSSL=false</value>

   </property>

<!-- jdbc 连接的 Driver-->

  <property>

       <name>javax.jdo.option.ConnectionDriverName</name>

       <value>com.mysql.jdbc.Driver</value>

   </property>

<!-- jdbc 连接的 username--> 

  <property>

       <name>javax.jdo.option.ConnectionUserName</name>

       <value>root</value>

   </property>

<!-- jdbc 连接的 password --> 

  <property>

       <name>javax.jdo.option.ConnectionPassword</name>

       <value>wl990922</value>

   </property>

<!-- Hive 元数据存储版本的验证 --> 

  <property>

   <name>hive.metastore.schema.verification</name>

   <value>false</value>

</property>

<!--元数据存储授权-->

  <property>

   <name>hive.metastore.event.db.notification.api.auth</name>

   <value>false</value>

</property>

<!--查询时展示表头-->

<property>

   <name>hive.cli.print.header</name>

   <value>true</value>

   <description>Whether to print the names of the columns in query output.

   </description>

</property>

<!--查询时展示当前数据库-->

<property>

   <name>hive.cli.print.current.db</name>

   <value>true</value>

   <description>Whether to include the current database in the Hive prompt.

   </description>

</property>

</configuration>
2.登录mysql并新建Hive元数据库并退出
mysql>create database metastore;
mysql>quit
3.初始化Hive元数据库
bin/schematool -initSchema -dbType mysql -verbose
**(注意:这一行必须出现在第一行,并且需要顶格,前面没有任何空格或其他字符),否则会出现以下错误**

image

4.使用元数据服务的方式访问Hive

在hive-site.xml文件中添加以下配置

<!-- 指定存储元数据要连接的地址 --> 


<property>

   <name>hive.metastore.uris</name>

   <value>thrift://hadoop102:9083</value>

</property>

启动 metastore

bin/hive --service metastore

注意: 启动后窗口不能再操作,需打开一个新的 shell 窗口做别的操作

5.Hive的数据类型

基本数据类型和java相似

测试插入一条数据

往里面insert值得时候出现以下错误

image

执行

SET hive.exec.mode.local.auto=true;就可以了

6.DDL数据定义

1.创建数据库

语法

CREATE DATABASE [IF NOT EXISTS] database_name

[COMMENT database_comment]   

[LOCATION hdfs_path]

[WITH DBPROPERTIES (property_name=property_value, ...)];

说明:[]中的数据可有可无

  • [IF NOT EXISTS]:如果不存在就创建,避免创建时存在的错误

  • [COMMENT database_comment]:字段注释说明

  • [LOCATION hdfs_path]:指定数据库在HDFS上存放的位置

create database if not exists testbase ;  #如果不存在此数据库则创建
2.查看数据库

查看数据库

show databases;

查看数据库信息

desc database test;

显示数据库详细信息

desc database extended test;

切换数据库

use test;
3.删除数据库

删除空数据库

drop database test;

如果数据库里面不为空,则使用 cascade关键字强制删除

drop database test cascade;
4.建表

建外部表,外部表的特征就是在删除表的时候,外部表只删除元数据,不删除HDFS上面的数据。

建表的时候使用以下语句,可以让存储的数据以 逗号分隔

row format delimited fields terminated by ',';
1.建一个外部表
create external table externalTest(id string,name string);

去mysql中查看TBLS这个表

image

删除外部表

drop table externalTest;

再次查看 mysql中的TBLS和HDFS上面的数据

image

image

发现只是删除了元数据,HDFS上面的数据还在

2.建一个管理表(内部表)
create table manage(id string);

image

删除管理表

drop table manage;

再次查看 mysql中的TBLS和HDFS上面的数据

image

image

发现元数据和HDFS上的数据都不在了

3. 管理表和外部表的互相转换

查询表的类型

des formatted aa;

image

将其转换为外部表

alter table aa set tblproperties ('EXTERNAL'='TRUE');

在mysql中查看表的类型

image

4.修改表名
alter table aa rename to aa_test;

image

5.一些表的操作

添加列

alter table test add columns(name string);

查询表结构

desc test

更新列

alter table test change column id test_id string;

替换列

alter table test replace columns(test_id string,test_name string);

7.DML数据操作

1.数据导入
load data [local] inpath '数据的 path' [overwrite] into table test [partition (partcol1=val1,...)];

参数说明:

  • load data:表示加载数据

  • local:表示从本地加载数据到 hive 表;否则从 HDFS 加载数据到 hive 表

  • inpath:表示加载数据的路径

  • overwrite:表示覆盖表中已有数据,否则表示追加

  • into table:表示加载到哪张表

  • student:表示具体的表

  • partition:表示上传到指定分区

1.加载本地数据到hive中
load data local inpath '/home/wl/hadoop-3.3.1/load.txt' into table default.load_test;

image

image

2.加载HDFS文件到hive中

先上传本地文件到HDFS

dfs -put '/home/wl/hadoop-3.3.1/load2.txt' /;

image

从HDFS上加载数据到hive中

load data inpath '/load2.txt' into table default.load_test;

image

3.加载数据覆盖表中已有的数据

先上传本地文件到HDFS上

dfs -put '/home/wl/hadoop-3.3.1/load3.txt' /;

加载数据覆盖表中已有的数据

load data inpath '/load3.txt' overwrite into table default.load_test;

image

4.通过查询语句向表中插入数据

根据单张表中的数据,插入数据

insert into table test2 select id from test;

insert into:以追加数据的方式插入到表或分区,原有数据不会删除

insert overwrite:会覆盖表中已存在的数据

多表插入数据

> from test

> insert into table test3

> select id

> insert into table test2

> select id;

根据查询结果来创建表

create table if not exists student3 as select id, name from student;

Import 数据到指定 Hive 表中

 import table student2 from '/user/hive/warehouse/export/student'; 
2.数据导出
1.insert导出

将查询的结果导出到本地

insert overwrite local directory '/home/wl/data/test' select * from test;

再去本地文件夹查看一下

image

导出成功

将查询结果导出并格式化到本地

insert overwrite local directory '/home/wl/data/test2'    row format delimited fields terminated by ','   select * from test4;

再去看看本地文件

image

将查询结果格式化导出到HDFS上面

insert overwrite directory '/test4' row format delimited fields terminated by ',' select * from test4;

查看一下HDFS上是否有

image

image

2. export命令导出到本HDFS
export table test4 to '/tes4test4';

image

3. 清除表中数据(Truncate)
 truncate table test4;

注意:Truncate 只能删除管理表,不能删除外部表中数据

image

8.分区表和分桶表

1.分区表

所谓分区表,就是在HDFS上进行分目录,分区表在一定程度上加快了查找效率,因为加入了分区,则不需要进行全表扫描了

下面来用案例解释一下分区表

应用场景: 假设一天的数据很大,需要按照时间段来存放,可以使用分区进行管理

1.创建一个分区表
>create table day01(id string,name string,address string)

> partitioned by (day string)

> row format delimited fields  terminated by ',';
2.准备数据

在本地写三个文件的数据

day01.txt

1001,胡图图,翻斗花园1001

1002,胡英俊,翻斗花园1002

1003,牛爷爷,翻斗花园1003

day02.txt

1111,张三,北京市

2222,李四,北京市

3333,王五,北京市

day03.txt

0001,测试01,测试地址01

0002,测试02,测试地址02

0003,测试03,测试地址03
3.加载数据到分区表
load data local inpath '/home/wl/data/day01.txt' into table day01 partition(day='2021-12-27');
load data local inpath '/home/wl/data/day02.txt' into table day01 partition(day='2021-12-26');
load data local inpath '/home/wl/data/day03.txt' into table day01 partition(day='2021-12-25');

查看一下HDFS上面的目录结构,发现是按照我们分区规则进行存放的

image

image

按分区查找一下数据

image

4.添加分区
alter table day01 add partition(day='2021-10-27') partition(day='2021-10-28');

注意:两个partition 之间 一定要用空格隔开!!!

image

5.删除分区
alter table day01 drop partition(day='2021-10-27'),partition(day='2021-10-28');

注意:两个partition 之间 一定要用逗号隔开!!!

image

image

6.查看分区

查看有多少个分区

show partitions day01; 

查看分区表的结构

desc formatted day01;
7.二级分区

当数据量特别大,希望按照小时来分区,这个时候就用到了二级分区

创建一个二级分区表

>create table day02(id string,name string,address string)

>partitioned by (day string,hours string)

>row format delimited fields terminated by ',';

加载数据进分区表

load data local inpath '/home/wl/data/day02.txt' into table day02 partition(day='2021-12-27',hours='10');
load data local inpath '/home/wl/data/day01.txt' into table day02 partition(day='2021-12-27',hours='18');
load data local inpath '/home/wl/data/day03.txt' into table day02 partition(day='2021-12-27',hours='13');

查看HDFS上的目录结构

image

image

查看一个分区中的数据

select * from day02 where day='2021-12-27' and hours='13';

image

8.分区数据查询问题

首先在HDFS上建一个文件夹

hadoop fs -mkdir /user/hive/warehouse/day01/day=2021-12-28

然后往里面插入数据

hadoop fs -put  /home/wl/data/day01.txt /user/hive/warehouse/day01/day=2021-12-28

image

我们发现里面是有数据的,那么再去看看day01表中是否有 day=2021-12-28 数据

image

有以下三种解决方案:

1.修复命令

执行修复命令

msck repair table day01;

这个命令会去扫描HDFS上面的文件目录是否和mysql存储的元数据是否一致,如果不一致就会进行修复

image

再次查看表中的数据

image

2.手动添加分区

alter table day01 add partition(day='2021-12-28')

3.创建文件夹后 load 数据到分区

将本地的数据load进表中

load data local inpath '/home/wl/data/day01.txt' into table default.day01 partition(day='2021-12-28');
9.动态分区

根据某个特定的字段进行分区,无需写死

创建一个分区表

>create table day03(id string ,name string)

>partitioned by (address string)

>row format delimited fields terminated by ',';

往分区中加载数据

动态分区的列必须在查询语句的最后

insert into table day03 partition(address) select id,name,address from day02;

这里报错是因为动态分区的模式,默认 strict,表示必须指定至少一个分区为 静态分区,nonstrict 模式表示允许所有的分区字段都可以使用动态分区。

image

我们发现,分区按照地址进行动态分区

image

image

2.分桶表

将数据拆分成文件进桶里面存储

创建分桶表

>create table bucket(id int ,name string)

> clustered by(id)

> into 4 buckets

> row format delimited fields terminated by ',';

准备数据

1001,胡图图

1002,黑猫警长

1003,蝎子精

1004,大熊

1005,叮当猫

1006,柯南

1007,牛爷爷

1008,胡英俊

1009,穿山甲

1010,蛇精

加载数据

load data local inpath '/home/wl/data/bucket.txt' into table bucket;

注意:这里分桶需要有一个注意的点,因为默认reducer的个数为1,所以分桶的时候会出现以下错误

image

在hive中配置reducer的个数

set mapred.reduce.tasks = 5;

9.函数

1.系统内置函数

查看系统自带的函数

show functions;

显示自带的函数的用法

desc function when;

展示自带函数的详细用法

desc function extended when;
2.常用内置函数
1.NVL函数-空字段赋值

image

用法 :nvl(values,default_values):表示如果value的值不是空的则返回value,否则返回default_value

创建一个表

>create table nvlTest(id int,name string,depno string)

>row format delimited fields terminated by ',';

往表中加载数据

load data local inpath '/home/wl/data/nvlTest.txt' into table nvlTest;

image

使用nvl函数进行处理

 select nvl(id,depno),name,depno from nvltest;

image

2.CASE WHEN THEN ELSE END

建表

>create table emp(name string,dep_name string,sex string)

>row format delimited fields terminated by ',';

数据准备

image

需求 :求出不同部门男女各多少人

> select

> dep_name,

> sum (case sex when '男' then 1 else 0 end) maleCount,

> sum(case sex when '女' then 1 else 0 end) femaleCount

> from emp

> group by dep_name;

image

3.行转列

拼接函数:

  • COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重 汇总,产生 Array 类型字段。
  • CONCAT_WS(separator, str1, str2,...):它是一个特殊形式的 CONCAT()。第一个参数剩余参

数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将 为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接 的字符串之间

COLLECT_SET的使用:

select collect_set(name) from test1;

image

CONCAT_WS的使用

select concat_ws('-','a','b','c','d');

image

建表

>create table constellation(name string,constellation string,blood_type  string)

>row format delimited fields terminated by ',';

数据准备

胡图图,白羊座,A

胡英俊,射手座,A

张美丽,白羊座,B

牛爷爷,射手座,A

猪八戒,射手座,A

孙悟空,白羊座,B

加载数据

load data local inpath '/home/wl/data/constellation.txt' into table constellation;

image

需求:把星座和血型一样的人归类到一起

射手座,A        胡英俊|牛爷爷|猪八戒

白羊座,A        胡图图

白羊座,B        张美丽|孙悟空

思路:

1.首先先把星座和血型拼接起来

select concat_ws(',',constellation,blood_type) con_blood ,name from constellation;

image

2.聚合相同星座血型的人名

SELECT

        con_blood,

        collect_set ( NAME ) name_arr 

FROM

        (

        SELECT

                concat_ws( ',', constellation, blood_type ) con_blood,

        NAME 

        FROM

                constellation 

        ) t1 

GROUP BY

        con_blood;

image

3.完成操作

SELECT

        con_blood,

        concat_ws( '|', name_arr ) 

FROM

        (

        SELECT

                con_blood,

                collect_set ( NAME ) name_arr 

        FROM

                (

                SELECT

                        concat_ws( ',', constellation, blood_type ) con_blood,

                NAME 

                FROM

                        constellation 

                ) t1 

GROUP BY

        con_blood) t2;

image

4.列转行

查看explode函数的使用

image

建表测试

>create table movie(movie_name string,movie_type string)

>row format delimited fields terminated by '|';

数据准备

大耳朵图图|悬疑,恐怖,科幻,战争

黑猫警长|悬疑,警匪,动作,心理,剧情 

熊出没|战争,动作,灾难 

加载数据

load data local inpath '/home/wl/data/movie.txt' into table split_table;

image

使用explode函数

image

> SELECT

>         movie_name,

>         movie_types

> FROM

>         movie lateral VIEW explode (

>         split (movie_type,"," )) movie_tmp AS movie_types;

image

10.Kotlin连接Hive

1.启动元数据服务
bin/hive --service metastore
2.启动Hserver2服务

在Hive中conf目录下,在hive-site.xml里面添加以下内容

 <!-- 指定 hiveserver2 连接的 host -->



<property>

   <name>hive.server2.thrift.bind.host</name>

<value>wlwl</value>

</property>

<!-- 指定 hiveserver2 连接的端口号 -->

 <property>

   <name>hive.server2.thrift.port</name>

   <value>10000</value>

</property>

启动h2服务

bin/hive --service hiveserver2
3.启动beeline 客户端
bin/beeline -u jdbc:hive2://wlwl:10000/default

发现出现了以下错误

image

解决方案:

在hadoop中的core-site.xml中添加以下内容

  <property>    

    <name>hadoop.proxyuser.root.hosts</name>    

    <value>*</value>

  </property> 

  <property>    

    <name>hadoop.proxyuser.root.groups</name>    

    <value>*</value> 

  </property>

看到以下界面说明,连接成功

image

4.IDEA中创建Kotlin工程连接Hserver2

gradle内容如下

plugins {

    id 'org.jetbrains.kotlin.jvm' version '1.4.32'

}



group 'org.example'

version '1.0-SNAPSHOT'



repositories {

    mavenCentral()

}



dependencies {

    implementation "org.jetbrains.kotlin:kotlin-stdlib"

    implementation 'org.apache.hive:hive-jdbc:2.3.2'

    implementation 'org.apache.hadoop:hadoop-common:3.1.1'

    implementation 'org.apache.hadoop:hadoop-client:3.2.2'

    implementation 'org.apache.hive:hive-metastore:2.3.8'

}

2.连接代码如下

fun main(){

    var stmt:Statement?

    var conn:Connection?

    var rs:ResultSet?

    // 定义路径

    val url="jdbc:hive2://wlwl:10000/default"

    // 反射注册Driver

    Class.forName("org.apache.hive.jdbc.HiveDriver")

    // 获取连接

    conn=DriverManager.getConnection(url)

    stmt=conn.createStatement()

    // 执行sql

    val sql="select * from test"

    rs=stmt.executeQuery(sql)

    // 获取值

    while (rs.next()){

        print(rs.getString("test_id")+"\t")

        print(rs.getString("test_name"))

        println()

    }

}

查看hive中的test

image

和kotlin执行的结果一致

image

posted @ 2021-12-28 14:44  没有梦想的java菜鸟  阅读(141)  评论(0编辑  收藏  举报