Hive3.1 安装配置与底层存储原理
前言:基于自建Hadoop集群,单节点配置hive服务,主要用于验证工作中的hsql和hive的底层表架构原理(hive外部表数据在哪,分区表在hadoop是怎么存储的等等)。纸上得来终觉浅,绝知此事要躬行。
环境:Centos7 + hadoop3.2 + hive3.1 + mysql8.0
mysql+ 驱动 百度盘:
链接:https://pan.baidu.com/s/1au9lPimW2mrF6sVcQQczHQ
提取码:qwer
mysql-8.0.28-1.el7.x86_64.rpm-bundle.tar 优快云加速加载地址(不含mysql驱动)
目录:
-
- 建表原理介绍
- Hsql DDL建表语法树
- 原生数据类型/复杂数据类型(常用的)
- 创建普通表(内部表,不分区)
- 外部表建表测试
- 分区表建表测试
–
-
mysql 安装配置
# 1.卸载Centos7自带mariadb > rpm -qa|grep mariadb mariadb-libs-5.5.68-1.el7.x86_64 > rpm -e mariadb-libs-5.5.68-1.el7.x86_64 --nodeps # 2. 解压 > mkdir mysql-8.0.28_install > tar -xvf mysql-8.0.28-1.el7.x86_64.rpm-bundle.tar -C mysql-8.0.28_install # 3. 安装依赖插件 > yum install openssl-devel # 4.安装mysql(注意Mysql-community-server最后安装,rpm包前后有依赖关系) > rpm -ivh mysql-community-common-8.0.28-1.el7.x86_64.rpm > rpm -ivh mysql-community-client-plugins-8.0.28-1.el7.x86_64.rpm > rpm -ivh mysql-community-libs-8.0.28-1.el7.x86_64.rpm > rpm -ivh mysql-community-libs-compat-8.0.28-1.el7.x86_64.rpm > rpm -ivh mysql-community-devel-8.0.28-1.el7.x86_64.rpm > rpm -ivh mysql-community-client-8.0.28-1.el7.x86_64.rpm > rpm -ivh mysql-community-embedded-compat-8.0.28-1.el7.x86_64.rpm > rpm -ivh mysql-community-icu-data-files-8.0.28-1.el7.x86_64.rpm > rpm -ivh mysql-community-server-8.0.28-1.el7.x86_64.rpm # 5. 启动mysql服务 > systemctl start mysqld # 启动 > systemctl restart mysqld # 重启 > systemctl stop mysqld # 停止 > systemctl status mysqld # 查看状态 # 6. 修改mysql 密码(降低Mysql密码复杂度校验) #查看生成的临时密码 > cat /var/log/mysqld.log # 连接服务 > mysql -u root -p Enter password: #这里输入在日志中生成的临时密码 # 修改密码(mysql8 密码要求复杂程度比较高) mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'C+#ZwZj-t3eql'; # 将密码复杂度校验调整简单类型 mysql> set global validate_password.policy = 0; # 设置密码最少位数限制为 4 位 mysql> set global validate_password.length = 4; # 再次修改密码 mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY 'hadoop'; # 7. 创建新账户,允许远程访问 create user 'hadoop'@'%' IDENTIFIED WITH mysql_native_password BY 'hadoop'; # 新用户授权 grant all on *.* to 'hadoop'@'%'; # 8. 测试新用户登录 > mysql -u hadoop -p # 9. 建议设置为开机自启动服务 > systemctl enable mysqld
-
hive 安装配置
# 1. 解压安装包 > tar -zxvf apache-hive-3.1.2-bin.tar.gz #2. 解决hadoop、hive之间guava版本差异(两边版本保持一致,谁版本高复制谁) > cd ./apache-hive-3.1.2-bin/ > rm -rf hadoop-3.2.0/share/hadoop/common/lib/guava-11.0.2-jre.jar > cp ./lib/guava-19.0.jar ../hadoop-3.2.0/share/hadoop/common/lib/ # 注意:集群内hadoop都得修改一下 > scp /home/hadoop/app/hadoop-3.2.0/share/hadoop/common/lib/guava-19.0.jar hadoop02:/home/hadoop/ app/hadoop-3.2.0/share/hadoop/common/lib/ #3. 添加mysql jdbc驱动到hive安装包lib/文件下 > cp mysql-connector-java-8.0.23.redhat-00001.jar ./lib #4. 修改hive环境变量文件 添加Hadoop_HOME > cd ./apache-hive-3.1.2-bin/conf/ > mv hive-env.sh.template hive-env.sh > vim hive-env.sh export HADOOP_HOME=/home/hadoop/app/hadoop-3.2.0/ export HIVE_CONF_DIR=/home/hadoop/app/apache-hive-3.1.2-bin/conf/ # 5. 新增hive-site.xml 配置mysql等相关信息 vim hive-site.xml #-----------------hive-site.xml-------------- <configuration> <!-- 存储元数据mysql相关配置 --> <property> <name>javax.jdo.option.ConnectionURL</name> <value> jdbc:mysql://hadoop01:3306/hive?createDatabaseIfNotExist=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8</value> </property> <property> <name>javax.jdo.option.ConnectionDriverName</name> <value>com.mysql.jdbc.Driver</value> </property> <property> <name>javax.jdo.option.ConnectionUserName</name> <value>hadoop</value> </property> <property> <name>javax.jdo.option.ConnectionPassword</name> <value>hadoop</value> </property> <!-- HS2运行绑定host --> <property> <name>hive.server2.thrift.bind.host</name> <value>hadoop01</value> </property> <property> <name>hive.server2.thrift.port</name> <value>10000</value> # 默认 </property> <!-- 远程模式部署metastore 服务地址 --> <property> <name>hive.metastore.uris</name> <value>thrift://hadoop01:9083</value> </property> <!-- Hive 默认在 HDFS 中的工作目录 --> <property> <name>hive.metastore.warehouse.dir</name> <value>/user/hive/warehouse</value> # 默认 </property> <!-- 关闭元数据存储授权 --> <property> <name>hive.metastore.event.db.notification.api.auth</name> <value>false</value> </property> <!-- 关闭元数据存储版本的验证 --> <property> <name>hive.metastore.schema.verification</name> <value>false</value> </property> </configuration> # 7. hadoop开启用户代理 > vim core-site.xml # 追加(记得重启hadoop服务) <property> <name>hadoop.proxyuser.hadoop.hosts</name> <value>*</value> </property> <property> <name>hadoop.proxyuser.hadoop.groups</name> <value>*</value> </property> #8. 初始化metadata # 添加hive环境变量 > vim /etc/profile export HIVE_HOME=/home/hadoop/app/apache-hive-3.1.2-bin export PATH=${HIVE_HOME}/bin:$PATH > source /etc/profile # 使配置生效 # 初始化 > schematool -initSchema -dbType mysql -verbos #初始化成功会在mysql中创建74张表 > mysql -u hadoop -p mysql> show databases; >> 多出hive 库 mysql> use hive; mysql> show tables; >>'74 rows in set (0.00 sec)' #9. Metastore和Hiveserver2启动(停止服务jps + kill) > mkdir hive_logs > nohup hive --service metastore &> /home/hadoop/app/apache-hive-3.1.2-bin/hive_logs/metastore-start.logs & > nohup hive --service hiveserver2 &> /home/hadoop/app/apache-hive-3.1.2-bin/hive_logs/hiveserver2-start.logs & #10. 测试hive-client 和beeline连接 > hive > beeline -u jdbc:hive2://hadoop01:10000 -n hadoop
-
hive 建表测试(外部表、分区\分桶表)
-
建表原理介绍:
原理:将结构化的数据文件映射为一张数据表(所谓的建表就是描述一个数据文件,可以是csv、
text,也可以是其他结构化文件)
-
Hsql DDL建表语法树
# []:代表里面内容可以不写 -- 常用建表语句 create [temporary 临时表] [external 内部表/外部表] table [if not exists] [db_name.] table_name (col_name data_type[comment '字段描述语言'],col_name data_type,.....) [comment '整张表描述语言'] -- 创建分区表(分区字段不能和表中字段重复) [partitioned by (col_name data_type[comment '字段描述语言'],col_name data_type,.....)] -- 创建分桶表(分桶字段为表内字段) [clustered by (col_name,col_name...) [sorted by (col_name [asc|desc],...)] into num_buckets buckets] -- 指定数据文件分隔 [row format delimited [fields terminated by ''] --字段之间分隔符 [collection items terminated by ''] -- 集合元素之间分隔符 [map keys terminatedby ''] -- Map映射kv之间分隔符 [lines terminated by ''] -- 行数据之间分隔符 |serde...] --Hive 读写文件机制 -- 文件存储格式 [stored as file_format] -- 指定文件hdfs存储路径(默认hdfs/user/hive/warehouse);路径格式字符串 [location 'hdfs_path'] -- 向表中添加自定义或预定义的元数据属性,并设置它们的赋值 [tblproperties (property_name=property_value,...)]
-
原生数据类型/复杂数据类型(常用的)
原生数据类型:int,double,date,timestamp,string 复杂数据类型:array<datatype>,map<key_type,value_type>
-
创建内部表(不分区,数据文件一般存储在/user/hive/warehouse下)
-
未建任何表时,查看hadoop中设置的hive存储目录(/user/hive/warehouse)
user目录下没有/user/hive 路径
-
建库
-- 建表前,先建一个库(否者使用default库) > create database if not exists test_db;
执行建库语句后,dfs系统下出现 /user/hive/warehouse,且warehouse存在一个库名.db(test_db.db)的文件夹
-
建表
-- 建表 > use test_db > create table if not exists table_putong (id int comment 'id',name string comment '姓名',age int comment '年龄',loadtime string comment '加载日期') row format delimited fields terminated by ',';--指定数据字段分割符
建表后,在test_db.db目录下,出现了一个 和表名table_putong一致的文件夹
-
将一份txt 文件 put 到 表名文件夹table_putong下,执行表查看语句。
> vim test_data.txt ''' 1,张三,16,20220312 2,李四,18,20220313 3,王五,36,20220314 ''' > hadoop fs -put test_data.txt /user/hive/warehouse/test_db.db/table_putong/
beeline> select * from table_putong;
查询结果:
由此也可以验证建表原理,将指定位置指定格式的数据文件映射成表。
-
-
外部表建表测试
- 外部表理解:
1.内部表元数据和数据文件生命周期都有hive控制,执行删除表时,元数据和数据文件会一起删除。
2.外部表只有元数据生命周期由hive控制,执行删除表时,会删除表的元数据信息,但表数据文件还
存在hdfs中。
-
创建外部表
-- 单独创建外部表存储目录 > hadoop fs -mkdir /tt -- 创建外部表(关键词 external) beeline> use test_db; beeline> create external table test_external (id int comment 'id',name string comment '姓名',age int comment '年龄',loadtime string comment '加载日期') row format delimited fields terminated by ',' location '/tt';
-
外部表加载数据
# 方式1:和内部表一样,直接将数据放到对应hive表名的目录下 > hadoop fs -put test_data.txt /tt/ beeline> select * from test_external; # 方式2: sql语法插入(数据量少,插入也很慢,要起mapreduce) beeline> insert into test_external values(4,'插入数据',12,'20220824'); beeline> select * from test_external;
方式1查询结果:
方式2查询结果:(执行插入报错:“Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster”,解决见附录)
-
分区表建表测试
-
分区表理解:
-
Hive实际是存储在HDFS上的抽象,一个库对应一个目录,库里的表对应其子目录,表里的数据对应表目录里面的数据文件。
Hive表设置分区,相当于在表目录下面,再创建一个对应名字为 “分区列=分区值” 的子目录,子目录里面放所在分区的数据。分区字段并不是一个实际字段。
分区表作用:缩小数据查询范围,提高查询速度和性能。
-
静态分区:静态分区的分区列值是在编译时期,通过用户传递来决定的;
-
动态分区:动态分区只有在SQL执行时才能决定。
-
-
创建分区表
-- 创建静态分区表 beeline> create table test_partition (id int,name string,age int)comment'测试分区表' partitioned by (dt string comment '分区字段') row format delimited fields terminated by ',' ; -- 创建其他临时表(分区表插入数据时使用) beeline> create temporary table test_partition_temp (id int,name string,age int,dt string) row format delimited fields terminated by ',';
-
分区表加载数据
-- 1. 静态分区加载数据(静态分区,分区的属性值是由用户在加载数据的时候手动指定的) -- load语法: load data [local] inpath 'local_path/hdfs_path' [overwrite] into table 分区表 partition(分区字段='分区属性值'); -- loacl:是否加载本地文件 -- overwrite: 是否覆盖重写 -- 加载hdfs文件 beeline> load data inpath '/tt/test_external.txt' into table test_partition partition(dt='20220728'); -- 不设定local 默认HDFS 路径,加载本质是hadoop fs -mv /xx,原文件移动 -- 加载本地文件数据 beeline> load data local inpath '/home/hadoop/app/test_data/test_external.txt' into table test_partition partition(dt='20220728',tt='多重分区存在的话'); -- 加载本地文件为 cp 拷贝操作 -- insert 语法 INSERT [OVERWRITE|into] TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement; -- 插入数据 beeline> insert into table test_partition partition(dt='20221001') select * from test_external; ----------------------------------------------------------------------------- -- 2. 动态分区加载数据(动态分区,分区的字段值是基于sql 查询结果(参数位置)自动推断出来的) -- 配置准备:set hive.exec.dynamic.partition=true; # 是否开启动态分区功能 -- set hive.exec.dynamic.partition.mode=nonstrict; # 指定动态分区模式, nonstrict:非严格模式/strict:严格模式 -- 加载数据 beeline> insert into table test_partition_dynamic partition(dt) select t.id,t.name,t.age,t.dt from test_partition_temp t;
附录
# hive 执行插入时,mapreduce程序报错““Could not find or load main class org.apache.hadoop.mapreduce.v2.app.MRAppMaster”” # 命令行查看日志mapreduce 具体执行情况 yarn application -list -appStates ALL # 显示所有任务 yarn logs -applicationId application_1659056678692_0002 # 查看具体任务日志 # 解决:根据日志提示,“<value>HADOOP_MAPRED_HOME=${full path of your hadoop distribution directory}</value> ” 配置一下信息 # 1.获取hadoop 加载class类路径 命令行 > hadoop classpath; " /home/hadoop/app/hadoop-3.2.0/etc/hadoop:/home/hadoop/app/hadoop-3.2.0/share/hadoop/common/lib/*:/home/hadoop/app/hadoop-3.2.0/share/hadoop/common/*:/home/hadoop/app/hadoop-3.2.0/share/hadoop/hdfs:/home/hadoop/app/hadoop-3.2.0/share/hadoop/hdfs/lib/*:/home/hadoop/app/hadoop-3.2.0/share/hadoop/hdfs/*:/home/hadoop/app/hadoop-3.2.0/share/hadoop/mapreduce/lib/*:/home/hadoop/app/hadoop-3.2.0/share/hadoop/mapreduce/*:/home/hadoop/app/hadoop-3.2.0/share/hadoop/yarn:/home/hadoop/app/hadoop-3.2.0/share/hadoop/yarn/lib/*:/home/hadoop/app/hadoop-3.2.0/share/hadoop/yarn/* " # 2. vim yarn-site.xml <property> <!-- --> <name>yarn.application.classpath</name> <value>${hadoop classpath}</value> # 将hadoop classpath命令返回结果粘贴至此。 </property> # 3. vim mapred-site.xml <property> <!-- --> <name>mapreduce.application.classpath</name> <value>${hadoop classpath}</value> </property> <property> <!--设置hadoop 家目录 --> <name>yarn.app.mapreduce.am.env</name> <value>HADOOP_MAPRED_HOME=/home/hadoop/app/hadoop-3.2.0</value> </property> <property> <!-- --> <name>mapreduce.map.env</name> <value>HADOOP_MAPRED_HOME=/home/hadoop/app/hadoop-3.2.0</value> </property> <property> <!-- --> <name>mapreduce.reduce.env</name> <value>HADOOP_MAPRED_HOME=/home/hadoop/app/hadoop-3.2.0</value> </property>
-
-