浅谈Hive

是什么

Hive是Hadoop生态的数据仓库工具
Hive将存储在HDFS上的文件映射为关系表
通过解析开发者提交的SQL语句,将SQL转换成MR任务,提交到Hadoop执行
Hive提供了命令行客户端和JDBC

Hive架构

file

Hive 安装

将Hive的元数据库替换为mysql

  • hive自带关系型数据库derby用于存储hive中的库和表的结构信息(metadata)
  • 生产环境中通常将derby替换为mysql等性能更好的开源数据库
  1. yum
yum install mysql
  1. 使用安装包进行离线安装

    • 下载mysql安装包
    • 使用脚本自动化安装
#!/bin/bash
echo -e "33[4;40;31m欢迎使用mysql离线安装自动化脚本 v1.033[0m"
echo -e "33[4;40;31m作者:Amos QQ:410507803 E-Mail:[email protected][0mn"

read -p "请输入mysql8的zx压缩包文件所在路径(eg:/opt/mysql8.xxx.xz):" FILE_PATH
read -p "请输入想要安装的目录(eg:/usr/local/mysql):" DEST_PATH

rpm -e --nodeps $(rpm -qa | grep mariadb)

echo -e "33[40;32m   (1/13)正在解压,请耐心等待解压过程约1-3分钟... 33[0m"
tar Jxf $FILE_PATH -C .
echo -e "33[40;32m   解压完成 33[0m"

echo -e "33[40;32m   (2/13)移动加压后的文件到$DEST_PATH 33[0m"
mv mysql-8*x86_64 $DEST_PATH

echo -e "33[40;32m   (3/13)添加环境变量$DEST_PATH 33[0m"
echo "export MYSQL_HOME=$DEST_PATH" >>/etc/profile
echo 'export PATH=.:$MYSQL_HOME/bin:$PATH' >>/etc/profile
source /etc/profile

echo -e "33[40;32m   (4/13)创建data目录 33[0m"
mkdir $DEST_PATH/data

echo -e "33[40;32m   (5/13)创建my.cnf配置文件 33[0m"
rm -rf /etc/my.cnf
echo "
[client]
port=3306
socket=/tmp/mysql.sock
[mysqld]
port=3306
user=mysql
socket=/tmp/mysql.sock
basedir=$DEST_PATH
datadir=$DEST_PATH/data
log-error=$DEST_PATH/error.log
pid-file = $DEST_PATH/mysql.pid
transaction_isolation = READ-COMMITTED
character-set-server = utf8
collation-server = utf8_general_ci
lower_case_table_names = 1
" > /etc/my.cnf
echo 'sql_mode = "STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE,ERROR_FOR_DIVISION_BY_ZERO"' >> /etc/my.cnf

echo -e "33[40;32m   (6/13)创建mysql组 33[0m"
groupadd mysql

echo -e "33[40;32m   (7/13)创建mysql用户并加入mysql组 33[0m"
useradd -g mysql mysql

echo -e "33[40;32m   (8/13)修改安装目录权限和所有者 33[0m"
chown -R mysql:mysql $DEST_PATH
chmod -R 755 $DEST_PATH

echo -e "33[40;32m   (9/13)初始化mysql 33[0m"
$DEST_PATH/bin/mysqld --initialize --user=mysql

echo -e "33[40;32m   (10/13)尝试启动mysql 33[0m"
$DEST_PATH/support-files/mysql.server start

echo -e "33[40;32m   (11/13)将mysqld添加为服务并设置开机自启动 33[0m"
cp $DEST_PATH/support-files/mysql.server /etc/init.d/mysqld
chmod 755 /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig --level 345 mysqld on

echo -e "33[40;32m   (12/13)重启mysql 33[0m"
service mysqld restart

echo -e "33[40;32m   (13/13)读取临时密码 33[0m"
TEMP_PW=$(cat $DEST_PATH/error.log | grep 'password' | awk -F' ' '{print $NF}')

echo -e "

33[40;32m  mysql的初始临时密码为:$TEMP_PW 33[0m

33[40;32m  使用初始密码登录mysql后,您可以使用如下SQL修改初始密码: 33[0m
33[40;33m  ALTER user 'root'@'localhost' IDENTIFIED BY 'a123456'; 33[0m

33[40;32m  使用如下SQL添加可远程访问的root用户: 33[0m
33[40;33m  CREATE USER 'root'@'%' IDENTIFIED WITH mysql_native_password  BY 'a123456'; 33[0m
33[40;33m  GRANT ALL ON *.* TO 'root'@'%'; 33[0m
33[40;33m  FLUSH PRIVILEGES; 33[0m

33[40;32m  3秒后将使用初始密码登录mysql,感谢您的使用 33[0m
"

sleep 3

mysql -uroot -p$TEMP_PW

安装Hive

  1. 上传解压

  2. 修改配置文件

    • hive-env.sh
HADOOP_HOME=/opt/hadoop-2.7.7
HIVE_CONF_DIR=/opt/hive-2.3.9/conf
JAVA_HOME=/opt/jdk1.8
  • hive-site.xml
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<configuration>
  <property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://bd0701:3306/metastore</value>
  </property>
  <property>
    <name>javax.jdo.option.ConnectionDriverName</name>
    <value>com.mysql.cj.jdbc.Driver</value>
  </property>
  <property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>root</value>
  </property>
  <property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>123456</value>
  </property>
</configuration>
- 将mysql驱动包上传到hive的lib中

- 初始化metastore
./schematool -initSchema -dbType mysql
  1. 配置环境变量
echo 'export HIVE_HOME=/opt/hive-2.3.9' >> /etc/profile
echo 'export PATH=$HIVE_HOME/bin:$PATH' >> /etc/profile
source /etc/profileCOPY
  1. 启动hive

    • hive提供了控制台操作方式

      # hive 用于启动终端
      hive
    • hive提供JDBC服务器的远程连接方式

      1. 修改hdfs的访问权限
        修改hadoop core-site.xml文件

        <property>
        <name>hadoop.proxyuser.root.hosts</name>
        <value>*</value>
        </property>
        <property>
        <name>hadoop.proxyuser.root.groups</name>
        <value>*</value>
        </property>
      2. 分发配置文件,并重启HDFS集群
      3. 使用hiveserver2 开启hive的JDBC服务器
      4. hive提供beeline客户端连接hive2服务
beeline
beeline> !connect jdbc:hive2://hostname:10000
beeline> root
beeline>
  1. 数据库连接工具远程连接 IDEA

Hive操作

DDL

-- 查看表
show tables;
-- 创建表
--  创建  外部     表    如果不存在      表名
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
-- (列名    数据类型    字段备注,)
[(col_name data_type [COMMENT col_comment], ...)]
-- 表备注
[COMMENT table_comment]
-- 设置表的分区字段  (字段名  类型)
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
-- 指定分桶 按照 (字段名)
[CLUSTERED BY (col_name, col_name, ...)
-- 在分桶过程中  按照某些字段排序
[SORTED BY (col_name [ASC|DESC], ...)]
-- 设置桶的个数
INTO num_buckets BUCKETS]
-- 行 格式
[ROW FORMAT
-- 受限于
DELIMITED
-- 字段  结束      于  字符
[FIELDS TERMINATED BY ' |- u0001']
-- 集合      元素  结束       于
[COLLECTION ITEMS TERMINATED BY ',']
-- 映射结构的kv之间的分隔符
[MAP KEYS TERMINATED BY ':']
-- 设置行结束符
[LINES TERMINATED BY 'n']]
-- 设置文件的存格式
-- text
-- ORC 是一种列式存储的数据格式,用于海量数据的存储和查询
[STORED AS file_format]
-- 设置当前表读取的HDFS路径
[LOCATION hdfs_path]
-- 查看表详情
desc table_name;
desc extended table_name;
desc formatted table_name;
-- 删除表
drop table table_name;
  • 截断表
-- 保留表的结构  移除所有的表内容
-- 只有管理表才能进行截断操作
truncate

DML

  • Hive底层将表的内容保存在HDFS,HDFS不支持文件的随机修改
  • 所以Hive也不支持表的字段修改和数据的update操作

数据导入

  • load data
-- 加载数据 本地    从某个路径    可以是本地路径或者hdfs路径
load data [local] inpath '/root/data/student.txt'
-- 是否覆盖   加载到 某个表
[overwrite] into table student
-- 添加分区字段
[partition (partcol1=val1,…)];
  • insert
-- 将后面的查询结果 写入到前表中
insert into table 表名 partition (分区字段) select语句;
  • as select
-- 通过查询结果创建新表
create table if not exists 表名  as select语句;
  • hdfs直接上传文件
-- 本质上Hive就是将表结构映射到HDFS文件,所以直接操作底层文件夹可以让Hive读取上传的文件,
-- 分区表 需要检查并修复分区
-- 检查表的行格式与原始数据是否一致,如果不规整的数据通常创建单列的表作为原始表
hdfs dfs -put 文件 表路径

数据导出

  • insert
-- 不加local则导出到HDFS路径
insert overwrite local directory '/output_t_weblog'
    row format delimited fields terminated by '|'
select *
from t_weblog_extracted_orc;
  • hdfs get
    如果Hive表使用text存储格式,则可以直接从表所在路径读取表的内容文件

  • hive自带的导入导出工具

-- 将表数据导出到hdfs路径
export table default.student to '/user/hive/warehouse/export/student';
import table student2 partition(month='202005') from '/user/hive/warehouse/export/student';

Sqoop

Sqoop使用手册 – AmosCloud

DQL

--             去重       HQL中通常需要使用各种函数对查询的字段进行处理
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
--  从哪个表查
  FROM db_ref.table_ref t1, (select xxx) t2
--  添加过滤条件
  [WHERE where_condition]
--  分组 MR底层指定分区条件
  [GROUP BY col_list]
--  排序 (全局排序) MR要实现全局排序 就只能启动1个reducer
  [ORDER BY col_list]
-- 如果MR分区和排序的字段 是同一个字段,则可以直接使用 CLUSTER by
  [CLUSTER BY col_list
--     指定按某些字段进行分布 (MR分区,自定义partitioner)
    | [DISTRIBUTE BY col_list]
--     指定分区内的排序方式 (MR 中的shuffle排序)
      [SORT BY col_list]
  ]
-- 限制读取原始数据的条数
 [LIMIT number]

Hive的函数

Hive的内建函数

-- 列出所有可用的函数
show functions;

-- 查看某个函数的用法
desc function substr;

-- 查看函数的详细用法(包含案例)
desc function extended substr;

Hive也提供用户自定义函数的方式 添加函数

  • 所有hive函数都放在org.apache.hadoop.hive.ql.udf包中

  • 自定义函数的过程

    1. 创建maven工程引入依赖hive-exec
    2. 编写类 继承 org.apache.hadoop.hive.ql.udf.UDF
    3. 编写方法 evaluate ,方法名不能变,但允许重载
    4. 将工程打成jar上传到HDFS
    5. 在Hive中创建函数
create [temporary] function db_name.func_name as '类的引用' using jar 'hdfsJar路径';

Hive的核心原理

外部表和管理表(内部表)

  • 区别
    创建时 外部表需要添加external
    删除时 管理表会删除元数据(mysql)和表的内容数据(HDFS)
    外部表仅仅删除元数据(mysql)

表的分区

-- 创建表t_weblog
create external table db_test01.t_weblog
(
    line string
);
-- 加载数据 11-01 ~11-05 加载到表中
-- load data inpath 'hdfs路径'  into table 表名;
-- hdfs dfs -mv 'hdfs路径' 表名路径
-- load data local inpath 'linux路径'  into table 表名;
-- hdfs dfs -put 'linux路径' 表名路径
-- load data [local] inpath '路径' into table 表名
select *
from t_weblog
limit 10;

-- 统计11月2日访问的用户数量
-- 02/Nov/2021
-- [06/Nov/2021:03:37:21 +0800]
select t1.dt, count(*) count
from (select substr(split(line, ' ')[3], 2, 11) dt
      from t_weblog) t1
where t1.dt = '02/Nov/2021'
group by t1.dt;

-- 上述方式 将所有历史存量数据直接保存在表中
-- 会导致每次对表的查询都会加载所有的历史存量数据
--   因为底层MR 会将整个表的hdfs路径作为输入路径
-- FileInputFormat.setInputPath(job,new Path("hdfs/.../t_weblog"))

-- 创建Hive表  以日期作为分区字段
create external table t_weblog_par1
(
    line string
)
    partitioned by (dt string);

show tables;

desc t_weblog_par1;
line                    string
dt                      string
# Partition Information
# col_name              data_type               comment
dt                      string

-- 分区字段可以具有与表的列字段相同功能的查询和条件语句
-- select * from t where  分区字段
-- FileInputFormat.setInputPath(
-- job,new Path("hdfs/.../t_weblog/dt=20211102")
-- 指定分区后,查询 会直接加载表中的子目录 避免加载全表数据

create external table t_weblog_par2
(
    line string
)
    partitioned by (y string, m string, d string);
-- 分区可以支持按照顺序嵌套的多级分区,通产使用年、月、日  年月、日  作为分区字段

-- 如果使用load data将数据加载到表的分区中
-- 则Hive会自动添加分区信息到metastore中

-- 如果使用flume或者手动通过hdfs客户都创建分区目录 并上传文件
-- 则表在使用由于确实metastore中的分区信息,可能导致分区数据无法读取
-- 需要修复分区信息
msck repair table t_weblog_par2;

select m from t_weblog_par2
group by m limit 10;

表的分桶操作

-- 数据清洗  提取  ip  dt  code  url  up down

create table t_weblog_extracted as
select t1.strs[0]                                 ip,
       substr(t1.strs[3], 2, 11)                  dt,
       t1.strs[8]                                 code,
       substr(t1.strs[5], 2)                      type,
       t1.strs[6]                                 url,
       cast(t1.strs[9] as bigint)                 up,
       cast(t1.strs[size(t1.strs) - 1] as bigint) down
from (select split(line, ' ') strs from t_weblog) t1;

show create table t_weblog_extracted;

-- 创建分桶表  按照响应码  将数据分散到11个桶文件中
CREATE TABLE `t_weblog_extracted_bkt`
(
    `ip`   string,
    `dt`   string,
    `code` string,
    `type` string,
    `url`  string,
    `up`   bigint,
    `down` bigint
)
    clustered by (code)
        into 11 buckets;

-- 将非分桶表的数据 查询并插入支持分桶的表t_weblog_extracted_bkt
insert into t_weblog_extracted_bkt
select *
from t_weblog_extracted;

-- 底层MR会根据表设置的桶的个数 自动启动若干个reducer将数据输出到桶个数个文件中

-- 一个桶中可以存放多个key的数据
-- 一个key的数据不会给拆分到多个桶中

-- insert into table t2 select x
-- create table t2 as select x

-- 分桶后 按照分桶字段进行group by查询时,可以直接通过hash值寻找key所在的桶文件提高查询效率

-- 分桶时还可以指定按照哪些字段提前排序,排序可以增加按照key的数据扫描速度,因为在有序集合中  查找目标元素时,可以顺序读取目标元素所在的文件段

select code, count(*) count
from t_weblog_extracted
group by code
order by count desc;

desc t_weblog_extracted;

 

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇
下一篇>>