赞
踩
目录
5.1.2 row_number()、rank() 、dense_rank()的区别
Hive:由Facebook开源用于解决海量结构化日志的数据统计。
Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能。只能用来分析Hadoop中的结构化数据
本质是:将HQL转化成MapReduce程序
1)Hive处理的数据存储在HDFS
2)Hive分析数据底层的实现是MapReduce
3)执行程序运行在Yarn上
1. Hive2.x 开始官方不建议使用MapReduce引擎了,建议使用Tez或Spark引擎
2. 大数据计算引擎:
1)MapReduce
2)Tez(没有被广泛使用,通常和Hive一起使用)
3)Spark
4)Flink (在实时计算领域优于SPARK, 也支持在yarn上执行)
3. select * from table 不会产生MapReduce任务
Hive不支持修改和删除,侧重查询分析
数据库与数据仓库的本质区别是OLTP和OLAP的区别
版本选择及下载参考:https://hive.apache.org/downloads.html
略
cp hive-env.sh.template hive-env.sh
export HADOOP_HOME=/opt/module/hadoop-2.7.2
- <?xml version="1.0"?>
- <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
- <configuration>
- <property>
- <name>javax.jdo.option.ConnectionURL</name>
- <value>jdbc:mysql://linux01:3306/metastore?serverTimezone=Asia/Shanghai</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>123456</value>
- <description>password to use against metastore database</description>
- </property>
- </configuration>

!!需要手动创建hive元数据库metastore,注意此库必须是latin1,否则会出现奇怪问题!所以推荐手动创建!并且创建库之前不能有任意的hive操作,否则自动创建出来的库表将使用mysql默认的字符集,仍然报错!
!!另一种方法是修改mysql的配置文件,让mysql默认编码集就是latin1,这样hive自动创建的元数据库就是latin1的了,但是这已修改将会影响整个mysql数据库,如果mysql中有其他库,这种方式并不好。
- <property>
- <name>hadoop.proxyuser.root.hosts</name>
- <value>*</value>
- </property>
- <property>
- <name>hadoop.proxyuser.root.groups</name>
- <value>*</value>
- </property>
当 MySQL 部署好,Hive 配置修改好之后,启动 metastore 并不会自动初始化 metastore 库,需要手动执行初始化操作。Hive 自带了 schematool 用于初始化 metastore,命令如下:
bin/schematool -dbType mysql -initSchema
- # 进入hive
-
- bin/hive
-
- # 选择数据库
-
- hive> use default;
-
- # 创建表
- hive> create table t1 (id int, name string);
-
- # 插入数据
-
- hive> insert table t1 (id, name) values(1, "sanqian");
-
- # 查看数据
-
- hive> select * from t1;

优点:每列都是对齐的,方便查看
- # 启动hiveserver2服务
-
- bin/hiveserver2
-
- # 启动beeline
-
- bin/beeline
-
- # 连接hiveserver2
-
- beeline> !connect jdbc:hive2://linux01:10000
需要输入mysql的用户名和密码,如下图所示
0: jdbc:hive2://linux01:10000> show databases; +----------------+ | database_name | +----------------+ | default | +----------------+ 1 row selected (1.593 seconds) 0: jdbc:hive2://linux01:10000> use default; No rows affected (0.138 seconds) 0: jdbc:hive2://linux01:10000> show tables; +-----------+ | tab_name | +-----------+ | t1 | +-----------+ 1 row selected (0.146 seconds) 0: jdbc:hive2://linux01:10000> select * from t1; +--------+----------+ | t1.id | t1.name | +--------+----------+ | 1 | sanqian | +--------+----------+ 1 row selected (1.922 seconds) 0: jdbc:hive2://linux01:10000>
- <!-- Hive jdbc依赖-->
- <dependency>
- <groupId>org.apache.hive</groupId>
- <artifactId>hive-jdbc</artifactId>
- <version>2.3.9</version>
- </dependency>
- package com.sanqian.hive;
-
- import java.sql.*;
-
- /**
- * JDBC操作Hive
- * 注意: 需要先启动hiveserver2服务
- */
- public class HiveJdbcDemo {
- public static void main(String[] args) throws SQLException {
- // 指定hiveserver2的url链接
- String jdbcUrl = "jdbc:hive2://192.168.21.101:10000";
- // 获取连接,这里的user是指linux中的用户名,password随便指定即可
- Connection conn = DriverManager.getConnection(jdbcUrl, "root", "any");
- //获取Statement
- Statement stmt = conn.createStatement();
- //查询sql
- String sql = "select * from t1";
- //执行sql
- ResultSet res = stmt.executeQuery(sql);
- //循环读取结果
- while(res.next()){
- System.out.println(res.getInt("id") + "\t" + res.getString("name"));
- }
-
-
- }
- }

- hive> set hive.cli.print.current.db=true
- > ;
- hive (default)> set hive.cli.print.header=true;
- hive (default)> select * from t1;
- OK
- t1.id t1.name
- 1 sanqian
- Time taken: 6.35 seconds, Fetched: 1 row(s)
- hive (default)>
- set hive.cli.print.current.db=true;
- set hive.cli.print.header=true;
- <property>
- <name>hive.cli.print.header</name>
- <value>true</value>
- </property>
-
- <property>
- <name>hive.cli.print.current.db</name>
- <value>true</value>
- </property>
查看hive历史操作命令
tail -10 ~/.hivehistory
Hive的log默认存放在/tmp/root/hive.log目录下(当前用户名下)
修改hive的log存放日志到/opt/module/hive-2.3.9/logs
mv hive-log4j2.properties.template hive-log4j2.properties
mv hive-exec-log4j2.properties.template hive-exec-log4j2.properties
- # 查看数据库列表
- show databases;
- # 创建数据库
- create database mydb1;
- # 选择数据库
- use default;
- # 删除数据库
- drop database mydb1;
创建一个数据库会增加/user/hive/warehouse增加一个目录
会在metastore数据的dbs表中增加一行记录
- create table t2(
- id int comment 'ID',
- stu_name string comment 'name',
- stu_birthday date comment 'birthday',
- online boolean comment 'is online'
- )row format delimited fields terminated by '\t';
注意:写HQL语句时不能时使用table加空格,可以使用space
会在TBLS表中增加一条记录
行默认分隔符:\n (使用默认就行)
列默认分隔符:^A (可以使用ctrl + V ctrl + A 敲出)
数据
- 1 zhangsan 2022-10-02 true
- 2 lisi 2022-10-01 false
- 3 wangwu 2022-10-03 NULL
加载到表中
load data local inpath '/opt/lwx1087471/hive_data/t2.txt' into table t2;
# 查看有哪些表
show tables;
# 查看表信息
desc t2;
# 查看创建表的信息
show create table t2;
- hive (default)> show tables;
- OK
- tab_name
- t1
- t2
- t3
- Time taken: 0.018 seconds, Fetched: 3 row(s)
- hive (default)> desc t2;
- OK
- col_name data_type comment
- id int ID
- stu_name string name
- stu_birthday date birthday
- online boolean is online
- Time taken: 0.034 seconds, Fetched: 4 row(s)
- hive (default)> show create table t2;
- OK
- createtab_stmt
- CREATE TABLE `t2`(
- `id` int COMMENT 'ID',
- `stu_name` string COMMENT 'name',
- `stu_birthday` date COMMENT 'birthday',
- `online` boolean COMMENT 'is online')
- ROW FORMAT SERDE
- 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
- WITH SERDEPROPERTIES (
- 'field.delim'='\t',
- 'serialization.format'='\t')
- STORED AS INPUTFORMAT
- 'org.apache.hadoop.mapred.TextInputFormat'
- OUTPUTFORMAT
- 'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
- LOCATION
- 'hdfs://linux01:9000/user/hive/warehouse/t2'
- TBLPROPERTIES (
- 'transient_lastDdlTime'='1664829544')
- Time taken: 0.093 seconds, Fetched: 18 row(s)
- hive (default)>

#增加字段
alter table t2_bak add columns(address string);
# 删除表
drop table t2_bak
# 清空表
runcate table 表名
清空管理表,只清空数据
不能清空外部表
hive (default)> alter table t2 rename to t2_bak;
相应的HDFS的目录也会变化
- create table t4(
- id int comment 'ID',
- stu_name string comment 'name',
- stu_birthday date comment 'birthday',
- online boolean comment 'is online'
- )row format delimited fields terminated by '\t' lines terminated by '\n';
通常情况下不需要手动指定行分隔符使用默认\n就行
Hive有三种复杂数据类型ARRAY、MAP 和 STRUCT。ARRAY和MAP与Java中的Array和Map类似,而STRUCT与C语言中的Struct类似,它封装了一个命名字段集合,复杂数据类型允许任意层次的嵌套。
综合实战:
1)ARRAY字段存储用户的兴趣爱好
2)使用MAP字段存储学生的考试成绩
3)使用STRUCT字段存储员工地址信息
- create table student(
- id int comment 'ID',
- name string comment 'name',
- favors array<string> comment 'favors',
- scores map<string, int> comment 'scores',
- address struct<home_addr:string, office_add:string>
- )row format delimited
- fields terminated by '\t'
- collection items terminated by ','
- map keys terminated by ':'
- lines terminated by '\n';
- 1 zhangsan english,sing,swing chinese:80,math:90,english:100 beijing,shanghai
- 2 lisi games,coding chinese:79,math:85,english:95 guangzhou,shenzhen
-
-
- load data local inpath '/opt/xxx/hive_data/student.txt' into table student;
- hive (default)> select favors[0] from student;
- OK
- _c0
- english
- games
- hive (default)> select scores['chinese'] from student;
- OK
- _c0
- 80
- 79
- hive (default)> select address.home_addr from student;
- OK
- home_addr
- beijing
- guangzhou
内部表:
外部表:
内部表和外部表可以相互转化:
- # 内部表转外部表
- alter table tblName set tblproperties('external'='true')
- # 外部表转内部表
- alter table tblName set tblproperties('external'='false')
- create table partition_1(
- id int comment 'ID',
- name string comment 'name'
- )partitioned by (dt string)
- row format delimited
- fields terminated by '\t';
查看表信息
数据:原始数据不需要带分区字段
- 1 zhangsan
- 2 lisi
加载数据到分区表
load data local inpath '/opt/xxx/partition_1.txt' into table partition_1 partition(dt='20221004');
alter table partition_1 add partition(dt='20221005');
- hive (default)> show partitions partition_1;
- OK
- partition
- dt=20221004
- dt=20221005
alter table partition_1 drop partition(dt='20221005');
(1)使用load 加载数据
(2)使用put 传到对应的HDFS分区目录下
创建表
- create table partition_2(
- id int comment 'ID',
- name string comment 'name'
- )partitioned by (year int, school string)
- row format delimited
- fields terminated by '\t';
准备数据
1 zhangsan
2 lisi
3 wangwu
加载数据到分区
- load data local inpath '/opt/xxx/partition_2.txt' into table partition_2 partition(year=2022, school='xk');
- load data local inpath '/opt/xxx/partition_2.txt' into table partition_2 partition(year=2022, school='english');
- load data local inpath '/opt/xxx/partition_2.txt' into table partition_2 partition(year=2021, school='xk');
- load data local inpath '/opt/xxx/partition_2.txt' into table partition_2 partition(year=2021, school='english');
-
查看数据
select * from partition_2 where year=2022 and school='xk';
创建表:会在/data/ex_par创建一个目录
- create external table ex_par(
- id int comment 'ID',
- name string comment 'name'
- )partitioned by (dt string)
- row format delimited
- fields terminated by '\t'
- location '/data/ex_par';
加载数据
load data local inpath '/opt/lwx1087471/partition_2.txt' into table ex_par partition(dt='20221004');
删除分区
alter table ex_par drop partition(dt='20221004');
绑定已有的数据到指定分区
alter table ex_par add partition(dt='20221005') location '/data/ex_par/dt=20221004';
第二种方式工作中更常用(95%)
方式1: load data .... partition
方式2: 创建目录,上传数据,绑定已有的数据到指定分区。
使用场景:当按照某字段就行分区时,会出现数据倾斜的情况,这时可以使用桶表。从源头解决数据倾斜问题。
- # 创建桶表
-
- create table bucket_tb(
- id int comment 'ID'
- )clustered by (id) into 4 buckets;
-
- # 加载数据到临时表
- load data local inpath '/opt/lwx1087471/ids.txt' into table b_source;
-
- # 开启分桶功能
- set hive.enforce.bucketing=true
-
- # 插入数据
- insert into table bucket_tb select id from b_source where id is not null;
会产生四个文件
采样
- hive (default)> select * from bucket_tb tablesample(bucket 1 out of 4 on id);
- OK
- bucket_tb.id
- 16
- 12
- 8
- 4
- Time taken: 0.276 seconds, Fetched: 4 row(s)
提高查询效率
普通表join会产生笛卡尔积,使用桶表join会避免笛卡尔积
使用视图可以降低查询的复杂度
视图时一个逻辑表(虚拟表),删除视图不会给其他表造成任务影响
函数的基本操作
1)查看所有内置函数:show functions;
2)查看指定函数的信息:desc function FUNC;
3)查看指定函数的扩展信息:desc function extended FUNC;
hive支持的函数要比mysql多
窗口函数
格式:函数 over( partition by 字段 ,order by 字段 window_clause )
row_number():增加行号函数
over():函数工作的数据窗口
创建表
- create external table student_score(
- id int,
- name string,
- sub string,
- score int
- )row format delimited
- fields terminated by '\t'
- location '/data/student_score';
上传数据
hadoop fs -put score.txt /data/student_score/
写HQL
- select * from
- (select *, row_number() over(partition by sub order by score desc) as num from student_score
- ) as s where s.num<=3;
运行结果
区别:
1)row_number() : 增加行号,从1,...n 不重复
2)rank() : 排序允许并列,一旦有并列跳号,总数不会变
3)dense_rank() : 排序允许并列,一旦有并列不跳号,总数会减少
row_number()
rank()
dense_rank()
三个函数:
一般和group by 一起使用
- create external table student_favors(
- name string,
- favor string
- )row format delimited
- fields terminated by '\t'
- location '/data/student_favors';
- zs swing
- zs footbal
- zs sing
- zs codeing
- zs swing
hadoop fs -put student_favors.txt /data/student_favors/
select name,COLLECT_LIST(favor) as favors from student_favors group by name;
select name,COLLECT_SET(favor) as favors from student_favors group by name;
select name,CONCAT_WS(',',COLLECT_SET(favor)) as favors from student_favors group by name;
三个函数
案例
- create external table student_favors_2(
- name string,
- favors_list string
- )row format delimited
- fields terminated by '\t'
- location '/data/student_favors_2';
-
-
- zs swing,footbal,sing
- ls codeing,swing
hadoop fs -put student_favors_2.txt /data/student_favors_2/
select explode(split(favors_list, ',')) from student_favors_2;
- select name,favor from student_favors_2 lateral view
- explode(split(favors_list, ',')) t1 as favor;
排序
案例:
select id from bucket_tb order by id;
设置reduce个数:set mapreduce.job.reduces=2
select id from bucket_tb distribute by id sort by id;
select id from bucket_tb cluster by id;
group by 和distict的区别
需求:统计t1表中 去重后name的数据量
- 方式一:使用distinct
-
- select count(distinct name) from t1;
-
- 方式二: 使用group by
-
- selec count(*) from (select name from group by name) temp
使用方式一会把所有的数据shuffle到一个reduce中去做统计,性能不高。使用group by性能更高。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。