启动步骤
:::color2 su - hadoop:::
:::color2
#一键启动hdfs集群
start-dfs.sh
:::
一键关闭hdfs集群
stop-dfs.sh
:::color2
启动:start-yarn.sh
:::
停止:stop-yarn.sh
:::color2
历史服务器启动:mapred --daemon start historyserver
:::
:::color2
cd /export/server/hive
:::
启动元数据管理服务(必须启动,否则无法工作)
前台启动:bin/hive --service metastore
:::color2
后台启动:nohup bin/hive --service metastore >> logs/metastore.log 2>&1 &
:::
启动客户端端,二选一(当前先选择Hive Shell方式)Hive Shell方式(可以直接写SQL):bin/hive
:::tips
Hive ThriftServer方式(不可以直接写SQL,需要外部客户端链接使用):bin/hive --service hiveserver2
:::
启动元数据管理服务(必须启动,否则无法工作) 前台启动:bin/hive --service metastore 后台启动:nohup bin/hive --service metastore >> logs/metastore.log 2>&1 &
●启动客户端端,二选一(当前先选择Hive Shell方式) Hive Shell方式(可以直接写SQL):bin/hive Hive ThriftServer方式(不可以直接写SQL,需要外部客户端链接使用):bin/hive --service hiveserver2
使用代理客户端启用hive
:::color2
nohup bin/hive –service hiveserver2 >> logs/hiveserver2.log 2>&1 &
:::
启动:在hive目录输入bin/beeline
连接:!connect jdbc:hive2://node1:10000
输入用户名hadoop,密码跳过
VMware
网段设置
![](https://img-blog.csdnimg/img_convert/8dca3a7b1aabd0e79226f1f4c971fbdc.png)配置ip
![](https://img-blog.csdnimg/img_convert/e24b65cf270e18954caba4e9da729315.png)
vim /etc/sysconfig/network-scripts/ifcfg-ens33static
IPADDR=“192.168.88.103”
NETMASK=“255.255.255.0”
GATEWAY=“192.168.88.2”
DNS1=“192.168.88.2”
systemctl restart network
ifconfig
配置主机名映射
1.在Windows系统中修改hosts文件,填入如下内容:192.168.88.101 node1
192.168.88.102 node2
192.168.88.103 node3
2.在3台Linux的/etc/hosts文件中,填入如下内容(3台都要添加)
192.168.88.101 node1
192.168.88.102 node2
192.168.88.103 node3
ssh免密登录
![](https://img-blog.csdnimg/img_convert/fe111797587048b7b262f4ff0e2f5202.png)ssh-keygen -t rsa -b 4096
ssh-copy-id node1/2/3(三台机器都执行)
创建hadoop用户并配置免密登录
![](https://img-blog.csdnimg/img_convert/4807c4e9b6bbdec6cd08ca275a3d06ef.png)useradd hadoop
passwd hadoop
虚拟机jdk配置
![](https://img-blog.csdnimg/img_convert/d8c811d3a91c7dad94b8230960bcbfbc.png)上传到root文件夹
mkdir -p /export/server
tar -zxvf jdk-8u361-linux-x64.tar.gz -C /export/server/
cd /export/server
ln -s /export/server/jdk1.8.0_361 jdk
vim /etc/profile
export JAVA_HOME=/export/server/jdk
export PATH= P A T H : PATH: PATH:JAVA_HOME/bin
source /etc/profile
rm -f /usr/bin/java
ln -s /export/server/jdk/bin/java /usr/bin/java
jdkj复制到node2
scp r jdk1.8.0_361 node2:pwd
/
防火墙 SELinux 时间同步
![](https://img-blog.csdnimg/img_convert/55d952e9e09a9b6df49a0d22769dd0b4.png)systemctl stop firewalld
systemctl disable firewalld
vim /etc/sysconfig/selinux
SELINUX=disabled
重启:init 6
yum install -y ntp
rm -f /etc/localtime;sudo ln -s /usr/share/zoneinfo/Asia/shanghai /etc/localtime
ntpdate -u ntp.aliyun
systemctl start ntpd
systemctl enable ntpd
大数据软件生态
![](https://img-blog.csdnimg/img_convert/22c059e2c71ec4dd91e2ee2b44e5e1dd.png)hadoop分布式文件系统(HDFS)
架构
可以在多台服务器上构建存储集群,存储海量的数据。部署到虚拟机
![](https://img-blog.csdnimg/img_convert/0d0594008850706d5925c960af951539.png)tar -zxvf hadoop-3.3.4.tar.gz -C /export/server/
cd /export/server
ln -s /export/server/hadoop-3.3.4 hadoop
cd etc/hadoop
vim workers
node1
node2
node3
vim hadoop-env.sh
export JAVA_HOME=/export/server/jdk
export HADOOP_HOME=/export/server/hadoop
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export HADOOP_LOG_DIR=$HADOOP_HOME/logs
vim core-site.xml
修改
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://node1:8020</value>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
</configuration>
vim hdfs-site.xml
修改
<configuration>
<property>
<name>dfs.datanode.data.dir.perm</name>
<value>700</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/nn</value>
</property>
<property>
<name>dfs.namenode.hosts</name>
<value>node1,node2,node3</value>
</property>
<property>
<name>dfs.blocksize</name>
<value>268435456</value>
</property>
<property>
<name>dfs.namenode.handler.count</name>
<value>100</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/dn</value>
</property>
</configuration>
在node1节点:
mkdir -p /data/nn
mkdir /data/dn
在node2和node3节点:
mkdir -p /data/dn
分发
在node1执行如下命令
cd /export/server
scp -r hadoop-3.3.4 node2:pwd
/
scp -r hadoop-3.3.4 node3:pwd
/
在node2执行,为hadoop配置软链接
#在node2执行如下命令
ln -s /export/server/hadoop-3.3.4 hadoop
在node3执行,为hadoop配置软链接
#在node3执行如下命令
ln -s /export/server/hadoop-3.3.4 hadoop
vim /etc/profile
#在/etc/profile文件底部追加如下内容
export HADOOP_HOME=/export/server/hadoop
export PATH= P A T H : PATH: PATH:HADOOP_HOME/bin:$HADOOP_HOME/sbin
source /etc/profile
chown -R hadoop:hadoop /data
chown -R hadoop:hadoop /export
格式化namenode
#确保以hadoop用户执行
su - hadoop
**<font style="color:rgb(44, 44, 54);">su hadoop</font>**
:不加载目标用户的环境变量和配置文件,适合快速简单的用户切换。**<font style="color:rgb(44, 44, 54);">su - hadoop</font>**
:加载目标用户的环境变量和配置文件,适合需要完整环境配置的情况。
#格式化namenode
hadoop namenode -format
启动
#一键启动hdfs集群
start-dfs.sh
一键关闭hdfs集群
stop-dfs.sh
如果遇到命令未找到的错误,表明环境变量未配置好,可以以绝对路径执行
/export/server/hadoop/sbin/start-dfs.sh
/export/server/hadoop/sbin/stop-dfs.sh
:::danger
快照:hadoop的HDFS部署完成
:::
HDFS集群启停
**一键启停**#一键启动hdfs集群
start-dfs.sh
# 一键关闭hdfs集群
stop-dfs.sh
单进程启停
HDFS文件系统的操作命令
![](https://img-blog.csdnimg/img_convert/e64803cfe53bff72ac8fcb96b2129813.png)使用协议头:
两套命令系统
![](https://img-blog.csdnimg/img_convert/7aac35127b09392b6bad6d538b317501.png)创建文件夹
1. 使用`hadoop fs`命令:hadoop fs -mkdir [-p] <path> ...
- 使用
hdfs dfs
命令:
hdfs dfs -mkdir [-p] <path> ...
<path>
参数表示要创建的新目录的路径。
-p
选项的行为类似于Linux中的mkdir -p
命令,即如果指定的路径包含多级目录,则会递归地创建所有不存在的父目录。
下面是一些具体的示例:
hadoop fs -mkdir -p /itcast/bigdata
hdfs fs -mkdir -p /itheima/hadoop
查看指定目录下的内容
```plain hadoop fs -ls [-h] [-R] [path ...] hdfs dfs -ls [-h] [-R] [path ...] ```-ls
: 列出指定目录的内容。-h
: 人性化显示文件大小,即将字节数转换为更易读的形式(如 KB, MB, GB 等)。-R
: 递归列出目录及其所有子目录的内容。
示例
hadoop fs -ls /user/hadoop/input
hdfs dfs -ls /user/hadoop/input
上传文件到hdfs指定目录下
+ `hadoop fs -put [-f] [-p] ... ` + `hdfs dfs -put [-f] [-p] ... ` + `-f`: 覆盖目标文件。如果目标文件已经存在,使用 `-f` 选项会覆盖已有文件。 + `-p`: 保留属性。保留源文件的权限、所有权和其他元数据。 + ``: 指定要上传的本地文件或目录的路径。 + ``: 指定HDFS中存放文件的目标路径。示例
-
hadoop fs -put words.txt /itcast
: -
将本地文件
words.txt
上传至HDFS的/itcast
目录下。 -
hdfs dfs -put file:///etc/profile hdfs://node1:8020/itcast
: -
将本地文件
/etc/profile
上传至HDFS的node1:8020/itcast
目录下。
查看HDFS文件内容
+ `hadoop fs -cat ...` + `hdfs dfs -cat ...`示例
hadoop fs -cat /itcast/words.txt
:- 显示HDFS中
/itcast/words.txt
文件的所有内容。 hdfs dfs -cat /itcast/words.txt
:- 同样显示HDFS中
/itcast/words.txt
文件的所有内容。
处理大文件
对于较大的文件,直接使用 -cat
可能会导致输出过多,难以阅读。因此结合管道符 |
和 more
命令来分页查看文件内容:
hadoop fs -cat <src> | more
hdfs dfs -cat <src> | more
这里的 more
命令可以让用户逐页查看文件内容,按空格键翻页,按 q
键退出。
下载HDFS文件
+ `hadoop fs -get [-f] [-p] ... ` + `hdfs dfs -get [-f] [-p] ... ` + `-f`: 覆盖目标文件。如果目标文件已经存在,使用 `-f` 选项会覆盖已有文件。 + `-p`: 保留属性。保留源文件的权限、所有权和其他元数据。 + ``: 指定HDFS中要下载的文件或目录的路径。 + ``: 指定本地文件系统中保存文件的目标路径。示例
-
hadoop fs -get /itcast/zookeeper.out ./test
: -
下载HDFS中
/itcast/zookeeper.out
文件到本地文件系统中的./test
目录下。 -
hdfs dfs -get /itcast/zookeeper.out ./test
: -
同样的操作,但使用的是
hdfs dfs
命令。
拷贝HDFS文件
+ `hadoop fs -cp [-f] ... ` + `hdfs dfs -cp [-f] ... `-f
: 覆盖目标文件。如果目标文件已经存在,使用-f
选项会覆盖已有文件。<src>
: 指定HDFS中要复制的文件或目录的路径。<dst>
: 指定HDFS中接收文件的目标路径。
示例
hadoop fs -cp /small/1.txt /itcast
:- 复制HDFS中
/small/1.txt
文件到/itcast
目录下。 hadoop fs -cp /small/1.txt /itcast/666.txt
:- 复制HDFS中
/small/1.txt
文件到/itcast
目录下,并命名为666.txt
。
追加数据到HDFS文件
+ `hadoop fs -appendToFile ... ` + `hdfs dfs -appendToFile ... ` + ``: 指定一个或多个本地文件作为输入,这些文件的内容会被追加到HDFS中的目标文件。 + ``: 指定HDFS中要追加数据的目标文件路径。- 如果
<localsrc>
参数为-
,则从标准输入读取数据。 - 如果
<dst>
文件不存在,命令会先创建该文件再进行追加操作。
示例
echo "Hello World" | hadoop fs -appendToFile - /itcast/file.txt
: 将字符串 “Hello World” 写入标准输入,然后追加到HDFS中/itcast/file.txt
文件的末尾。hadoop fs -appendToFile localfile1.txt localfile2.txt /itcast/combinedfile.txt
: 将本地文件localfile1.txt
和localfile2.txt
的内容追加到HDFS中/itcast/combinedfile.txt
文件的末尾。
HDFS数据移动操作
+ `hadoop fs -mv ... ` + `hdfs dfs -mv ... ` + ``: 指定一个或多个源文件或目录的路径,这些是要被移动的对象。 + ``: 指定目标位置的路径,可以是一个新的文件名(如果是文件的话)或者一个新的目录(如果是整个目录树的话)。:::tips
- 移动文件或目录:将指定的文件或目录从一个位置移到另一个位置。
- 重命名文件:通过改变
<src>
和<dst>
的名称,可以达到重命名文件的目的。 - hadoop fs -mv /test2.txt /itheima/abc.txt
:::
示例
hadoop fs -mv /old/path/to/file /new/path/to/file
: 将文件从/old/path/to/file
移动到/new/path/to/file
。hdfs dfs -mv /old/path/to/directory /new/path/to/directory
: 将目录从/old/path/to/directory
移动到/new/path/to/directory
。
HDFS数据删除操作
+ `hadoop fs -rm -r [-skipTrash] URI [URI ...]` + `hdfs dfs -rm -r [-skipTrash] URI [URI ...]` + `-r`: 表示递归删除,即如果删除对象是目录,则会递归删除该目录及其所有子目录和文件。 + `-skipTrash`: 默认情况下,HDFS会在删除文件时将其移至回收站(.Trash)而非立即永久删除。使用 `-skipTrash` 选项可以直接跳过回收站,立即永久删除文件。 + `URI`: 指定要删除的文件或目录的路径。- 回收站功能默认关闭,若要开启需在
core-site.xml
文件中添加以下配置:
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
这里 fs.trash.interval
设置了回收站在多少分钟后自动清空,默认值为1440分钟(24小时)。
- 此外,还可以配置回收站的检查点间隔时间:
<property>
<name>fs.trash.checkpoint.interval</name>
<value>120</value>
</property>
这里 fs.trash.checkpoint.interval
设置了每隔多少秒检查一次是否有文件需要从回收站清除,默认值为120秒。
示例
hadoop fs -rm -r /path/to/file_or_directory
: 删除指定的文件或目录。hdfs dfs -rm -r -skipTrash /path/to/file_or_directory
: 不经过回收站,直接永久删除指定的文件或目录。
big data tool安装
IED下载插件NFS网关
把HDFS文件部署到win本地磁盘cd /export/server/hadoop/etc/hadoop/
vim core-site.xml
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>nfs.suerpser</name>
<value>hadoop</value>
</property>
<property>
<name>nfs.dump.dir</name>
<value>/tmp/.hdfs-nfs</value>
</property>
<property>
<name>nfs.exports.allowed.hosts</name>
<value>192.168.88.1 rw</value>
</property>
scp core-site.xml hdfs-site.xml node3: pwd
/
停止集群
exit 到root用户
systemctl stop nfs
systemctl disable nfs
yum remove -y rpcbind
hdfs --daemon start portmap
hdfs --daemon start nfs3
启动HDFS集群:start-dfs.sh
net use X: \192.168.88.101!
HDFS副本配置
![](https://img-blog.csdnimg/img_convert/5b86aa0888749c82577037576f3d262a.png)HDFS数据读写流程
![](https://img-blog.csdnimg/img_convert/79d0abe47cf9a51f6abd231547044b23.png)分布式计算MapReduce
![](https://img-blog.csdnimg/img_convert/636ed4538492b587497edd2a06ea2d89.png)MapReduce提供了2个编程接口:
Map
Reduce
其中 Map功能接口提供了“分散”的功能,由服务器分布式对数据进行处理
Reduce功能接口提供了“汇总(聚合)”的功能,将分布式的处理结果汇总统计
用户如需使用MapReduce框架完成自定义需求的程序开发需要使用lava、Python等编程语言,实现Map Reduce功能接口即可。
分布式资源调度YARN
![](https://img-blog.csdnimg/img_convert/a24c46b0550b84ab5c1465063e8bc2ff.png)YARN架构
![](https://img-blog.csdnimg/img_convert/82df9d5d2906da23630cd608ca4f9397.png)MapReduce配置文件
cd /export/server/hadoop/etc/hadoop/vim mapred-env.sh
# 设置JDK路径
export JAVA_HOME=/export/server/jdk
# 设置JobHistoryServer进程内存量为1G
export HADOOP_JOB_HISTORYSERVER_HEAPSIZE=1000
# 设置日志级别为INFO
export HADOOP_MAPRED_ROOT_LOGGER=INFO,RFA
vim mapred-site.xml
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
<description>MapReduce的运行框架设置为 YARN</description>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>node1:10020</value>
<description>历史服务器通讯端口为 node1:10020</description>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node1:19888</value>
<description>历史服务器web端口为 node1 的 19888</description>
</property>
<property>
<name>mapreduce.jobhistory.intermediate-done-dir</name>
<value>/data/mr-history/tmp</value>
<description>历史信息在HDFS的记录临时路径</description>
</property>
<property>
<name>mapreduce.jobhistory.done-dir</name>
<value>/data/mr-history/done</value>
<description>历史信息在HDFS的记录路径</description>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
<description>MapReduce HOME 设置为 $HADOOP_HOME</description>
</property>
<property>
<name>mapreduce.map.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
<description>MapReduce HOME 设置为 $HADOOP_HOME</description>
</property>
<property>
<name>mapreduce.reduce.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
<description>MapReduce HOME 设置为 $HADOOP_HOME</description>
</property>
YARN部署
![](https://img-blog.csdnimg/img_convert/42c3ae848e670803f9edadd509393985.png)# 设置 JDK 路径的环境变量
export JAVA_HOME=/export/server/jdk
# 设置 HADOOP_HOME 的环境变量
export HADOOP_HOME=/export/server/hadoop
# 设置配置文件路径的环境变量
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
# 设置日志文件路径的环境变量
export HADOOP_LOG_DIR=$HADOOP_HOME/logs
<property>
<name>yarn.resourcemanager.hostname</name>
<value>node1</value>
<description>ResourceManager设置在node1节点</description>
</property>
<property>
<name>yarn.nodemanager.local-dirs</name>
<value>/data/nm-local</value>
<description>NodeManager中间数据本地存储路径</description>
</property>
<property>
<name>yarn.nodemanager.log-dirs</name>
<value>/data/nm-log</value>
<description>NodeManager数据日志本地存储路径</description>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
<description>为MapReduce程序开启Shuffle服务</description>
</property>
<property>
<name>yarn.log.server.url</name>
<value>http://node1:19888/jobhistory/logs</value>
<description>历史服务器URL</description>
</property>
<property>
<name>yarn.web-proxy.address</name>
<value>node1:8089</value>
<description>代理服务器主机和端口</description>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
<description>开启日志聚合</description>
</property>
<property>
<name>yarn.nodemanager.remote-app-log-dir</name>
<value>/tmp/logs</value>
<description>程序日志HDFS的存储路径</description>
</property>
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
<description>选择公平调度器</description>
</property>
scp mapred-env.sh mapred-site.xml yarn-env.sh yarn-site.xml node2:`pwd`/
scp mapred-env.sh mapred-site.xml yarn-env.sh yarn-site.xml node3:`pwd`/
启动:start-yarn.sh
停止:stop-yarn.sh
历史服务器启动:mapred --daemon start historyserver
http://node1:8088
提交MapReduce程序至YARN运行
![](https://img-blog.csdnimg/img_convert/9f8435fcd7dc8296f40363c48037510c.png)cd /export/server/hadoop/share/hadoop/mapreduce
hadoop-mapreduce-examples-3.3.4.jar
- 输入路径:指定数据输入的HDFS(Hadoop Distributed File System)路径。
- 输出路径:指定结果输出的HDFS路径。
- 处理过程:对输入路径内的数据中的单词进行计数,并将结果写入到输出路径。
数据准备:
- 准备一份包含以下内容的数据文件
words.txt
,并上传到HDFS中:
itheima itcast itheima itcast hadoop hdfs hadoop hdfs hadoop mapreduce hadoop yarn itheima hadoop itcast hadoop itheima itcast hadoop yarn mapreduce
HDFS操作命令:
- 创建输入目录
/input/wordcount
:
hadoop fs -mkdir -p /input
- 创建输出目录
/output
:
hadoop fs -mkdir /output
- 将
words.txt
文件上传到HDFS的输入目录:
hadoop fs -put words.txt /input
执行MapReduce程序:
运行以下命令提交WordCount MapReduce程序到YARN执行:
hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.4.jar wordcount hdfs://node1:8020/input/ hdfs://node1:8020/output/wc
其中:
- 参数
wordcount
表示运行jar包中的单词计数程序(Java Class)。 - 第一个参数是数据输入路径 (
hdfs://node1:8020/input/wordcount/
)。 - 第二个参数是结果输出路径 (
hdfs://node1:8020/output/wc1
)。
通过这些步骤,可以实现对HDFS中特定路径下的文本文件进行单词计数,并将结果保存在指定的输出路径下。
分布式SQL计算-Hive
![](https://img-blog.csdnimg/img_convert/e596f2de9fb42529d5359ea806cf4e85.png)Hive在虚拟机部署
![](https://img-blog.csdnimg/img_convert/b4fa4d6527551a62ac85bd0ba3801625.png)# 更新密钥
rpm --import https://repo.mysql/RPM-GPG-KEY-mysql-2022
# 安装 MySQL yum 仓库
rpm -Uvh http://repo.mysql/mysql57-community-release-el7-7.noarch.rpm
# 使用 yum 安装 MySQL
yum -y install mysql-community-server
# 启动 MySQL 并设置为开机启动
systemctl start mysqld
systemctl enable mysqld
# 查看 MySQL 服务状态
systemctl status mysqld
# 获取临时密码
grep 'temporary password' /var/log/mysqld.log
#登录
mysql -uroot -p
# 设置密码策略为 LOW
set global validate_password_policy=LOW;
# 设置密码最小长度为 4
set global validate_password_length=4;
# 修改 root 用户密码
ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';
# 授予所有权限
grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;
# 刷新权限
flush privileges;
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>
su - hadoop
cd /export/server/hadoop/etc/hadoop/
vim core-site.xml
su - hadoop
wget http://archive.apache/dist/hive/hive-3.1.3/apache-hive-3.1.3-bin.tar.gz
tar -zxvf apache-hive-3.1.3-bin.tar.gz -C /export/server/
ln -s /export/server/apache-hive-3.1.3-bin hive
mv mysql-connector-java-5.1.34.jar /export/server/apache-hive-3.1.3-bin/lib/
cd have/conf
mv hive-env.sh.template hive-env.sh
vim hive-env.sh
export HADOOP_HOME=/export/server/hadoop
export HIVE_CONF_DIR=/export/server/hive
export HIVE_AUX_JARS_PATH=/export/server/hive/lib
vim hive-site.xml
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://node1: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>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<property>
<name>hive.server2.thrift.bind.host</name>
<value>node1</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://node1:9083</value>
</property>
<property>
<name>hive.metastore.event.db.notification.api.auth</name>
<value>false</value>
</property>
</configuration>
CREATE DATABASE hive CHARSET UTF8;
cd /export/server/hive
./bin/schematool -initSchema -dbType mysql -verbos
cd …
cd bin
./schematool -initSchema -dbType mysql -verbos
chown -R hadoop:hadoop apache-hive-3.1.3-bin hive
- 确保Hive文件夹所属为hadoop用户
- 创建一个hive的日志文件文件夹:
mkdir /export/server/hive/logs - 启动元数据管理服务(必须启动,否则无法工作)
前台启动:bin/hive --service metastore
后台启动:nohup bin/hive --service metastore >> logs/metastore.log 2>&1 & - 启动客户端端,二选一(当前先选择Hive Shell方式)
Hive Shell方式(可以直接写SQL):bin/hive
Hive ThriftServer方式(不可以直接写SQL,需要外部客户端链接使用):bin/hive --service hiveserver2
Hive体验执行SQL语句
首先,确保启动了Metastore服务。可以执行:bin/hive,进入到Hive Shell环境中,可以直接执行SQL语句。
- 创建表
CREATE TABLE test(id INT, name STRING, gender STRING);(没有指定数据库,自动创建到default数据库中)
- 插入数据
INSERT INTO test VALUES(1,‘王力红’,‘男’), (2,‘周杰轮’,‘男’), (3,‘林志灵’,‘女’);
- 查询数据
SELECT gender, COUNT(*) AS cnt FROM test GROUP BY gender;
Hive客户端
![](https://img-blog.csdnimg/img_convert/dcc392b2964fe2908b88908e7a03db08.png)HiveServer2服务
![](https://img-blog.csdnimg/img_convert/b8774666dc79cd834f6c41577e966d7b.png)nohup bin/hive --service hiveserver2 >> logs/hiveserver2.log 2>&1 &
beeline
![](https://img-blog.csdnimg/img_convert/03ece57dd5471f43f0d38e56450d5eb2.png)启动:在hive目录输入bin/beeline
连接:!connect jdbc:hive2://node1:10000
输入用户名hadoop,密码跳过
Hive语法
数据库操作
创建数据库
create database if not exists myhive;use myhive;
• 查看数据库详细信息
desc database myhive;
- 创建数据库并指定HDFS存储位置
create database myhive storage location '/myhive';
使用location关键字,可以指定数据库在HDFS上的存储路径。
删除数据库
+ 删除一个空数据库,如果数据库下面有数据表,那么就会报错drop database myhive;
- 强制删除数据库,包含数据库下面的表一起删除
drop database myhive cascade;
创建数据库表
```sql 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 row_format] [STORED AS file_format] [LOCATION hdfs_path] ```- EXTERNAL, 创建外部表
- PARTITIONED BY, 分区表
- CLUSTERED BY, 分桶表
- STORED AS, 存储格式
- LOCATION, 存储位置
内部表/外部表
在 Apache Hive 中,表可以分为两种类型:内部表(Managed Tables)和外部表(External Tables)。这两种表在管理和数据删除方面有一些重要的区别。内部表(Managed Tables)
- 定义:
- 内部表是由 Hive 完全管理的数据表。
- 当你创建一个内部表时,Hive 会在默认的仓库目录(通常是
hdfs://<namenode>:<port>/user/hive/warehouse
)下创建一个子目录来存储表的数据。
- 创建语法:
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
...
)
[PARTITIONED BY (column3 datatype, ...)]
[CLUSTERED BY (column4, ...) SORTED BY (column5) INTO num_buckets BUCKETS]
[ROW FORMAT DELIMITED FIELDS TERMINATED BY 'char']
[STORED AS file_format]
[LOCATION hdfs_path];
- 数据存储:
- 默认情况下,数据存储在 Hive 的仓库目录下的一个子目录中。
- 例如,如果你创建一个名为
employees
的表,数据将存储在hdfs://<namenode>:<port>/user/hive/warehouse/employees
目录下。
- 数据删除:
- 当你删除一个内部表时,Hive 不仅会删除表的元数据,还会删除表对应的数据文件。
- 例如:
DROP TABLE employees;
这条命令会删除 employees
表及其所有数据。
外部表(External Tables)
- 定义:
- 外部表是指数据存储在 Hive 仓库目录之外的表。
- 创建外部表时,你需要指定数据的实际存储位置。
- 创建语法:
CREATE EXTERNAL TABLE table_name (
column1 datatype,
column2 datatype,
...
)
[PARTITIONED BY (column3 datatype, ...)]
[CLUSTERED BY (column4, ...) SORTED BY (column5) INTO num_buckets BUCKETS]
[ROW FORMAT DELIMITED FIELDS TERMINATED BY 'char']
[STORED AS file_format]
LOCATION 'hdfs_path'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LOCATION '/tmp/test/test_extl1';
- 数据存储:
- 数据存储在你指定的 HDFS 路径下。
- 例如,如果你创建一个名为
external_employees
的外部表,并指定数据存储在/user/data/external_employees
目录下:
CREATE EXTERNAL TABLE external_employees (
id INT,
name STRING,
department STRING
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION '/user/data/external_employees';
- 数据删除:
- 当你删除一个外部表时,Hive 只会删除表的元数据,而不会删除表对应的数据文件。
- 例如:
DROP TABLE external_employees;
这条命令只会删除 external_employees
表的元数据,而不会删除存储在 /user/data/external_employees
目录下的数据文件。
总结
- 内部表:数据由 Hive 管理,删除表时会删除数据。因此内部表不适合和其他工具共享数据。
- 外部表:数据存储在指定的 HDFS 路径,删除表时只删除元数据,保留数据。
相互转换
hive数据的导入和导出
![](https://img-blog.csdnimg/img_convert/c9861e71e37f9979613a61c089a74eff.png)我们使用 LOAD 语法,从外部将数据加载到Hive内,语法如下:
LOAD DATA [LOCAL] INPATH ‘filepath’ [OVERWRITE] INTO TABLE tablename;
1:上传数据文件到Linux系统
2:创建表
CREATE TABLE myhive.test_load_load(
dt string COMMENT '时间(时分秒)',
user_id string COMMENT '用户ID',
word string COMMENT '搜索词',
url string COMMENT '用户访问网址'
) COMMENT '搜索引擎日志表'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
3:数据加载
load data local inpath '/home/hadoop/search_log.txt' [overwrite] into table myhive.test_load_load;
Hive 从Linux本地文件系统加载数据。关键字 <font style="color:rgb(44, 44, 54);">local</font>
表示数据源是在本地文件系统上的。
load data inpath '/tmp/search_log.txt' overwrite into table myhive.test_load;
Hive 从 HDFS 加载数据。源数据文件会消失(本质是被移动到表所在的目录中)
分区表
![](https://img-blog.csdnimg/img_convert/f7b56d5dddf628a3b5abd3c3289bbe95.png)。
分区表的概念
分区表是将表的数据按照一个或多个列的值分成多个部分,每个部分称为一个分区。每个分区可以存储在一个独立的目录中,这样在查询时可以根据分区条件快速定位到所需的数据。
创建分区表
单分区表
假设我们有一个日志表 `logs`,我们希望按日期进行分区。可以使用以下 SQL 语句创建单分区表:CREATE TABLE logs (
id INT,
message STRING
)
PARTITIONED BY (dt STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
在这个例子中,dt
列用于分区,每个分区将存储在不同的目录中。
多分区表
如果需要按多个列进行分区,可以使用多个 `PARTITIONED BY` 列。例如,按日期和小时进行分区:CREATE TABLE logs (
id INT,
message STRING
)
PARTITIONED BY (dt STRING, hr STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
查询分区表
查询分区表时,可以通过指定分区条件来提高查询效率。例如:SELECT * FROM logs WHERE dt = '2023-10-01';
删除分区
可以使用 `ALTER TABLE` 语句删除分区:ALTER TABLE logs DROP PARTITION (dt = '2023-10-01');
分桶表
分桶概念(Bucketing)
分桶是 Hive 中一种用于优化查询的技术,它通过将数据按照某个列的值进行哈希散列,并根据散列值将数据分布到多个文件中,这些文件被称为“桶”。每个桶可以看作是一个小的数据集,这样可以使得在处理大规模数据集时更加高效,尤其是在进行连接操作或者采样时。优点
- 提升查询效率:当需要对特定列进行过滤或聚合时,分桶可以减少需要扫描的数据量,从而加快查询速度。
- 并行处理:由于数据已经被均匀地分配到了不同的桶中,因此可以更容易地实现并行处理。
- 采样:对于大数据集,如果数据已经均匀地分布在各个桶中,那么从每个桶中抽取少量数据就可以得到一个代表性的样本,这对于数据探索和分析非常有用。
缺点
- 增加数据准备时间:创建分桶表时,需要额外的时间来计算哈希值并将数据正确地放入相应的桶中。
- 桶的数量选择:需要合理选择桶的数量,太少会导致数据倾斜,太多则可能增加存储开销和管理复杂度。
创建分桶表
在创建分桶表时,通常会指定一个或多个列作为分桶列,并指定桶的数量。例如,假设我们有一个用户行为日志表,我们希望基于用户的 `user_id` 进行分桶,可以这样创建表:set hive.enforce.bucketing=true;
CREATE TABLE user_behavior (
user_id INT,
action STRING,
time TIMESTAMP
)
CLUSTERED BY (user_id) INTO 32 BUCKETS
row format delimited fields terminated by '\t';
这里,CLUSTERED BY (user_id)
指定了分桶列,而 INTO 32 BUCKETS
则指定了将数据分为32个桶。
加载数据到分桶表
![](https://img-blog.csdnimg/img_convert/aacd87cf13aa3a5227dffa581edd197a.png)修改表的sql操作
1. 修改表注释
```sql ALTER TABLE table_name SET TBLPROPERTIES ('comment' = 'new_comment'); ```table_name
是你想要修改的表的名字,new_comment
是新的注释信息。
2. 表重命名
```sql ALTER TABLE old_table_name RENAME TO new_table_name; ```old_table_name
是当前表的名字,new_table_name
是新名字。
3. 添加列
```sql ALTER TABLE table_name ADD COLUMNS (column_name column_type [COMMENT 'column_comment']); ```table_name
是你要添加列的表的名字,column_name
是新列的名字,column_type
是新列的数据类型,可选的 COMMENT
用来提供列的说明。
4. 修改列名
```sql ALTER TABLE table_name CHANGE COLUMN old_column_name new_column_name column_type [COMMENT 'column_comment']; ```old_column_name
是旧列名,new_column_name
是新列名,column_type
是列的新数据类型,COMMENT
是可选的列说明。
5. 删除表
```sql DROP TABLE IF EXISTS table_name; ```IF EXISTS
是可选的,但建议加上,以防表不存在时出错。
6. 清空表
清除表中的所有数据,但保留表结构,无法清空外部表TRUNCATE TABLE table_name;
请注意,TRUNCATE 不同于 DELETE,因为它不会触发任何触发器,而且它的执行速度更快。
7.添加分区
使用 ` ALTER TABLE ... ADD PARTITION` 语句。例如,假设有一个按日期分区的表 ` web_logs` ,你可以这样添加一个新的分区:ALTER TABLE web_logs ADD PARTITION (dt='2024-01-01') LOCATION '/user/hive/warehouse/web_logs/dt=2024-01-01';
<font style="color:rgb(44, 44, 54);">dt</font>
是分区列,<font style="color:rgb(44, 44, 54);">2024-01-01</font>
是分区值,<font style="color:rgb(44, 44, 54);">LOCATION</font>
指定了分区数据在 HDFS 上的存储路径。如果不指定 <font style="color:rgb(44, 44, 54);">LOCATION</font>
,Hive 会默认在表的目录下创建一个子目录来存储该分区的数据。
8.删除分区
会删除hive里面的元数据,但是不会删除hdfs里面的数据文件。ALTER TABLE web_logs DROP PARTITION (dt='2024-01-01');
array数组
![](https://img-blog.csdnimg/img_convert/6af82229d97b1530a426278be651966e.png)可以使用array数组类型,存储locations的数据,要求数据类型一致
CREATE TABLE myhive.test_array(
name STRING,
work_locations ARRAY<STRING>
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ',';
SELECT id, name, courses[0] AS first_course FROM stu
SELECT id, name, size(courses) AS num_courses FROM students;
SELECT id, name, array_contains(courses, 'Math') AS has_math FROM students;
map映射
![](https://img-blog.csdnimg/img_convert/56bb972cedb2ba2359ea4ca356f99b43.png)create table myhive.test_map(
id int,
name string,
members map<string,string>,
age int
)
row format delimited
fields terminated by ','
COLLECTION ITEMS TERMINATED BY '#'
MAP KEYS TERMINATED BY ':';
select
id,
name,
members['father'],
members['mother']
from
myhive.test_map;
select
map_keys(members)
from
myhive.test_map;
-- ,看看谁有 sister 这个 key
SELECT *
FROM myhive.test_map
WHERE ARRAY_CONTAINS(map_keys(members), 'sister');
SELECT *
FROM myhive.test_map
WHERE ARRAY_CONTAINS(map_values(members), '王林');
struct数据类型
![](https://img-blog.csdnimg/img_convert/b3dee2bd1b6dba2d31d50ce9ec59ee9f.png) ![](https://img-blog.csdnimg/img_convert/6a8aba61c77010e986fea76751548589.png)CREATE TABLE myhive.test_struct (
id STRING,
info STRUCT<name:STRING, age:INT>
)#info是struct的整体列名
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '#'
COLLECTION ITEMS TERMINATED BY ':';
SELECT id, info.name, info.age
FROM myhive.test_struct;
基本查询
**1. SELECT 语句**SELECT
语句用于从表中选择数据。基本语法如下:
SELECT column1, column2, ...
FROM table_name;
2. 聚合函数
聚合函数用于对一组值进行计算并返回单个值。常见的聚合函数包括:
COUNT(*)
:计算行数。COUNT(column)
:计算指定列的非空值数量。SUM(column)
:计算指定列的总和。AVG(column)
:计算指定列的平均值。MIN(column)
:计算指定列的最小值。MAX(column)
:计算指定列的最大值。
-- 计算表中所有行的数量
SELECT COUNT(*) FROM sales;
-- 计算销售额的总和
SELECT SUM(amount) FROM sales;
-- 计算平均销售额
SELECT AVG(amount) FROM sales;
-- 计算最小和最大销售额
SELECT MIN(amount), MAX(amount) FROM sales;
3. GROUP BY 子句
GROUP BY
子句用于将数据分组,通常与聚合函数一起使用。语法如下:
SELECT column1, aggregate_function(column2)
FROM table_name
GROUP BY column1;
-- 按产品类别分组,计算每个类别的销售总额
SELECT category, SUM(amount) AS total_sales
FROM sales
GROUP BY category;
-- 按客户分组,计算每个客户的订单数量
SELECT customer, COUNT(order_id) AS order_count
FROM orders
GROUP BY customer;
4. JOIN 子句
JOIN
子句用于将多个表中的数据组合在一起。常见的 JOIN
类型包括:
INNER JOIN
:返回两个表中匹配的行。LEFT JOIN
:返回左表中的所有行,以及右表中匹配的行。如果没有匹配的行,则返回 NULL。RIGHT JOIN
:返回右表中的所有行,以及左表中匹配的行。如果没有匹配的行,则返回 NULL。FULL OUTER JOIN
:返回两个表中的所有行,如果没有匹配的行,则返回 NULL。
-- INNER JOIN 示例
SELECT o.order_id, o.customer, p.product_name, o.amount
FROM orders o
INNER JOIN products p ON o.product_id = p.product_id;
-- LEFT JOIN 示例
SELECT o.order_id, o.customer, p.product_name, o.amount
FROM orders o
LEFT JOIN products p ON o.product_id = p.product_id;
-- RIGHT JOIN 示例
SELECT o.order_id, o.customer, p.product_name, o.amount
FROM orders o
RIGHT JOIN products p ON o.product_id = p.product_id;
-- FULL OUTER JOIN 示例
SELECT o.order_id, o.customer, p.product_name, o.amount
FROM orders o
FULL OUTER JOIN products p ON o.product_id = p.product_id;
5. ORDER BY 子句
ORDER BY
子句用于对查询结果进行排序。语法如下:
SELECT column1, column2, ...
FROM table_name
ORDER BY column1 [ASC | DESC], column2 [ASC | DESC], ...;
-- 按销售额降序排列
SELECT customer, SUM(amount) AS total_sales
FROM sales
GROUP BY customer
ORDER BY total_sales DESC;
-- 按客户升序排列,按订单日期降序排列
SELECT customer, order_date, amount
FROM orders
ORDER BY customer ASC, order_date DESC;
正则表达式
![](https://img-blog.csdnimg/img_convert/15abeedf416088b4bad7cda556beef15.png):::color2
.中是对.的进一步解释,两个符号不是独立的存在
:::
union联合
union用于将多个select语句的结果组合成单个结果集。 每个select语句返回的列的数量和名称必须相同。否则,将引发架构错误。- UNION:合并结果集并去除重复行。
- UNION ALL:合并结果集并保留所有行,包括重复的行。
SELECT column1, column2, ...
FROM table1
UNION
SELECT column1, column2, ...
FROM table2
[UNION
SELECT column1, column2, ...
FROM table3]
...
采样(Sampling)
![](https://img-blog.csdnimg/img_convert/a889668f56a6d2646f3bd5854ccc5c75.png)1. 基于行的采样
基于行的采样使用 `TABLESAMPLE` 关键字,可以通过指定百分比或行数来抽取样本。SELECT *
FROM table_name
TABLESAMPLE (type AND expression);
按百分比采样
-- 抽取表中 10% 的行
SELECT *
FROM sales
TABLESAMPLE (10 PERCENT);
按行数采样
-- 抽取表中 1000 行
SELECT *
FROM sales
TABLESAMPLE (1000 ROWS);
2. 埋点采样(Bucket Sampling)
基于桶的采样是一种更精确的采样方法,它将数据分成多个桶,然后从每个桶中抽取样本。这种方法适用于大数据集,可以确保样本的均匀分布。x
:要抽取的桶编号。y
:总的桶数。- colname指代列名,表示根据给出的列名把数据分成y个桶,rand()表示把数据随机分桶。
假设我们有一个表 sales
,我们想从该表中抽取 1/10 的数据。
-- 将数据分成 10 个桶,抽取第 1 个桶的数据
SELECT *
FROM sales
TABLESAMPLE (BUCKET 1 OUT OF 10 ON date);
3. 随机采样
Hive 还支持使用随机函数进行采样。可以使用 `RAND()` 函数来抽取随机样本。-- 抽取表中随机的 10% 的行
SELECT *
FROM sales
WHERE RAND() <= 0.1;
虚拟列
![](https://img-blog.csdnimg/img_convert/e6a89fa9a8215a74fcd5827f6b31df70.png)案例
需求分析
建库建表
```sql --如果数据库已存在就删除 drop database if exists db_msg cascade ; --创建数据库 create database db_msg ; --切换数据库 use db_msg ; ```--建表
CREATE TABLE db_msg.tb_msg_source(
msg_time STRING COMMENT "消息发送时间",
sender_name STRING COMMENT "发送人昵称",
sender_account STRING COMMENT "发送人账号",
sender_sex STRING COMMENT "发送人性别",
sender_ip STRING COMMENT "发送人IP地址",
sender_os STRING COMMENT "发送人操作系统",
sender_phonetype STRING COMMENT "发送人手机型号",
sender_network STRING COMMENT "发送人网络类型",
sender_gps STRING COMMENT "发送人的GPS定位",
receiver_name STRING COMMENT "接收人昵称",
receiver_ip STRING COMMENT "接收人IP",
receiver_account STRING COMMENT "接收人账号",
receiver_os STRING COMMENT "接收人操作系统",
receiver_phonetype STRING COMMENT "接收人手机型号",
receiver_network STRING COMMENT "接收人网络类型",
receiver_gps STRING COMMENT "接收人的GPS定位",
receiver_sex STRING COMMENT "接收人性别",
msg_type STRING COMMENT "消息类型",
distance STRING COMMENT "双方距离",
message STRING COMMENT "消息内容"
);
- 数据文件上传到/home/hadoop,上传数据文件
- 创建hadoop文件夹,上传数据文件到hdfs
hadoop fs -mkdir -p /chatdemo/data
hadoop fs -put chat_data-5W.csv /chatdemo/data/
- 加载数据到表中
load data inpath '/chatdemo/data/chat_data-30W.csv' into table tb_msg_source;
ETL数据清洗
![](https://img-blog.csdnimg/img_convert/83b05bee47b0ac5c414000e859ad6dde.png)
// 创建新表
CREATE TABLE db_msg.tb_msg_etl(
msg_time STRING COMMENT "消息发送时间",
sender_name STRING COMMENT "发送人昵称",
sender_account STRING COMMENT "发送人账号",
sender_sex STRING COMMENT "发送人性别",
sender_ip STRING COMMENT "发送人IP地址",
sender_os STRING COMMENT "发送人操作系统",
sender_phonetype STRING COMMENT "发送人手机型号",
sender_network STRING COMMENT "发送人网络类型",
sender_gps STRING COMMENT "发送人的GPS定位",
receiver_name STRING COMMENT "接收人昵称",
receiver_ip STRING COMMENT "接收人IP",
receiver_account STRING COMMENT "接收人账号",
receiver_os STRING COMMENT "接收人操作系统",
receiver_phonetype STRING COMMENT "接收人手机型号",
receiver_network STRING COMMENT "接收人网络类型",
receiver_gps STRING COMMENT "接收人的GPS定位",
receiver_sex STRING COMMENT "接收人性别",
msg_type STRING COMMENT "消息类型",
distance STRING COMMENT "双方距离",
message STRING COMMENT "消息内容"
msg_day string comment "消息日",
msg_hour string comment "消息小时",
sender_lng double comment "经度",
sender_lat double comment "纬度"
);
SELECT
msg_time AS msg_time,
DATE(msg_time) AS msg_day,
*,
HOUR(msg_time) AS msg_hour,
SPLIT(sender_gps, ',')[0] AS sender_lng,
SPLIT(sender_gps, ',')[1] AS sender_lat
FROM db_msg.tb_msg_source
WHERE LENGTH(sender_gps) > 0;
指标计算
![](https://img-blog.csdnimg/img_convert/ed8c8c387a92383c0b0500880d58f286.png)// 统计今日消息总量
CREATE TABLE db_msg.tb_rs_total_msg_cnt COMMENT '每日消息总量' AS
SELECT msg_day, COUNT(*) AS total_msg_cnt FROM db_msg.tb_msg_etl GROUP BY msg_day;
-- 需求2:统计每小时的消息量、发送和接受的用户数量
create table db_msg.tb_rs_hour_msg_cnt comment '每小时消息量趋势' as
SELECT
msg_hour,
COUNT(*) AS total_msg_cnt,
COUNT(DISTINCT sender_account) AS sender_user_cnt,
COUNT(DISTINCT receiver_account) AS receiver_user_cnt
FROM db_msg.tb_msg_etl
GROUP BY msg_hour;
-- 统计今日各地区发送消息总数量
CREATE TABLE db_msg.tb_rs_loc_cnt
COMMENT '今日各地区发送消息总数量'
AS
SELECT
msg_day,
sender_lng,
sender_lat,
COUNT(*) AS total_msg_cnt
FROM db_msg.tb_msg_etl
GROUP BY msg_day, sender_lng, sender_lat;
-- 统计今日发送和接收用户的数量
CREATE TABLE db_msg.tb_rs_user_cnt
COMMENT '每日发送和接收消息的人数'
AS
SELECT
msg_day,
COUNT(DISTINCT sender_account) AS sender_user_cnt,
COUNT(DISTINCT receiver_account) AS receiver_user_cnt
FROM db_msg.tb_msg_etl
GROUP BY msg_day;
-- 统计发送消息最多的Top10用户
CREATE TABLE db_msg.tb_rs_s_user_top10
COMMENT '发送消息最多的10个用户'
AS
SELECT
sender_name,
COUNT(*) AS sender_msg_cnt
FROM db_msg.tb_msg_etl
GROUP BY sender_name
ORDER BY sender_msg_cnt DESC
LIMIT 10;
-- 统计接收消息最多的Top10用户
CREATE TABLE db_msg.tb_rs_r_user_top10
COMMENT '接收消息最多的10个用户'
AS
SELECT
receiver_name,
COUNT(*) AS receiver_msg_cnt
FROM db_msg.tb_msg_etl
GROUP BY receiver_name
ORDER BY receiver_msg_cnt DESC
LIMIT 10;
-- 统计发送人的手机型号分布情况
CREATE TABLE db_msg.tb_rs_sender_phone
COMMENT '发送人的手机型号分布'
AS
SELECT
sender_phonetype,
COUNT(*) AS cnt
FROM db_msg.tb_msg_etl
GROUP BY sender_phonetype;
-- 统计发送人的手机操作系统分布情况
CREATE TABLE db_msg.tb_rs_sender_os
COMMENT '发送人的手机型号分布'
AS
SELECT
sender_os,
COUNT(*) AS cnt
FROM db_msg.tb_msg_etl
GROUP BY sender_os;
可视化展现
![](https://img-blog.csdnimg/img_convert/eb7357ddd0444ec3f84e69ccbea4e7d9.png)激活码:
启动步骤
:::color2 su - hadoop:::
:::color2
#一键启动hdfs集群
start-dfs.sh
:::
一键关闭hdfs集群
stop-dfs.sh
:::color2
启动:start-yarn.sh
:::
停止:stop-yarn.sh
:::color2
历史服务器启动:mapred --daemon start historyserver
:::
:::color2
cd /export/server/hive
:::
启动元数据管理服务(必须启动,否则无法工作)
前台启动:bin/hive --service metastore
:::color2
后台启动:nohup bin/hive --service metastore >> logs/metastore.log 2>&1 &
:::
启动客户端端,二选一(当前先选择Hive Shell方式)Hive Shell方式(可以直接写SQL):bin/hive
:::tips
Hive ThriftServer方式(不可以直接写SQL,需要外部客户端链接使用):bin/hive --service hiveserver2
:::
启动元数据管理服务(必须启动,否则无法工作) 前台启动:bin/hive --service metastore 后台启动:nohup bin/hive --service metastore >> logs/metastore.log 2>&1 &
●启动客户端端,二选一(当前先选择Hive Shell方式) Hive Shell方式(可以直接写SQL):bin/hive Hive ThriftServer方式(不可以直接写SQL,需要外部客户端链接使用):bin/hive --service hiveserver2
使用代理客户端启用hive
:::color2
nohup bin/hive –service hiveserver2 >> logs/hiveserver2.log 2>&1 &
:::
启动:在hive目录输入bin/beeline
连接:!connect jdbc:hive2://node1:10000
输入用户名hadoop,密码跳过
VMware
网段设置
![](https://img-blog.csdnimg/img_convert/8dca3a7b1aabd0e79226f1f4c971fbdc.png)配置ip
![](https://img-blog.csdnimg/img_convert/e24b65cf270e18954caba4e9da729315.png)
vim /etc/sysconfig/network-scripts/ifcfg-ens33static
IPADDR=“192.168.88.103”
NETMASK=“255.255.255.0”
GATEWAY=“192.168.88.2”
DNS1=“192.168.88.2”
systemctl restart network
ifconfig
配置主机名映射
1.在Windows系统中修改hosts文件,填入如下内容:192.168.88.101 node1
192.168.88.102 node2
192.168.88.103 node3
2.在3台Linux的/etc/hosts文件中,填入如下内容(3台都要添加)
192.168.88.101 node1
192.168.88.102 node2
192.168.88.103 node3
ssh免密登录
![](https://img-blog.csdnimg/img_convert/fe111797587048b7b262f4ff0e2f5202.png)ssh-keygen -t rsa -b 4096
ssh-copy-id node1/2/3(三台机器都执行)
创建hadoop用户并配置免密登录
![](https://img-blog.csdnimg/img_convert/4807c4e9b6bbdec6cd08ca275a3d06ef.png)useradd hadoop
passwd hadoop
虚拟机jdk配置
![](https://img-blog.csdnimg/img_convert/d8c811d3a91c7dad94b8230960bcbfbc.png)上传到root文件夹
mkdir -p /export/server
tar -zxvf jdk-8u361-linux-x64.tar.gz -C /export/server/
cd /export/server
ln -s /export/server/jdk1.8.0_361 jdk
vim /etc/profile
export JAVA_HOME=/export/server/jdk
export PATH= P A T H : PATH: PATH:JAVA_HOME/bin
source /etc/profile
rm -f /usr/bin/java
ln -s /export/server/jdk/bin/java /usr/bin/java
jdkj复制到node2
scp r jdk1.8.0_361 node2:pwd
/
防火墙 SELinux 时间同步
![](https://img-blog.csdnimg/img_convert/55d952e9e09a9b6df49a0d22769dd0b4.png)systemctl stop firewalld
systemctl disable firewalld
vim /etc/sysconfig/selinux
SELINUX=disabled
重启:init 6
yum install -y ntp
rm -f /etc/localtime;sudo ln -s /usr/share/zoneinfo/Asia/shanghai /etc/localtime
ntpdate -u ntp.aliyun
systemctl start ntpd
systemctl enable ntpd
大数据软件生态
![](https://img-blog.csdnimg/img_convert/22c059e2c71ec4dd91e2ee2b44e5e1dd.png)hadoop分布式文件系统(HDFS)
架构
可以在多台服务器上构建存储集群,存储海量的数据。部署到虚拟机
![](https://img-blog.csdnimg/img_convert/0d0594008850706d5925c960af951539.png)tar -zxvf hadoop-3.3.4.tar.gz -C /export/server/
cd /export/server
ln -s /export/server/hadoop-3.3.4 hadoop
cd etc/hadoop
vim workers
node1
node2
node3
vim hadoop-env.sh
export JAVA_HOME=/export/server/jdk
export HADOOP_HOME=/export/server/hadoop
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
export HADOOP_LOG_DIR=$HADOOP_HOME/logs
vim core-site.xml
修改
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://node1:8020</value>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
</configuration>
vim hdfs-site.xml
修改
<configuration>
<property>
<name>dfs.datanode.data.dir.perm</name>
<value>700</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/data/nn</value>
</property>
<property>
<name>dfs.namenode.hosts</name>
<value>node1,node2,node3</value>
</property>
<property>
<name>dfs.blocksize</name>
<value>268435456</value>
</property>
<property>
<name>dfs.namenode.handler.count</name>
<value>100</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/data/dn</value>
</property>
</configuration>
在node1节点:
mkdir -p /data/nn
mkdir /data/dn
在node2和node3节点:
mkdir -p /data/dn
分发
在node1执行如下命令
cd /export/server
scp -r hadoop-3.3.4 node2:pwd
/
scp -r hadoop-3.3.4 node3:pwd
/
在node2执行,为hadoop配置软链接
#在node2执行如下命令
ln -s /export/server/hadoop-3.3.4 hadoop
在node3执行,为hadoop配置软链接
#在node3执行如下命令
ln -s /export/server/hadoop-3.3.4 hadoop
vim /etc/profile
#在/etc/profile文件底部追加如下内容
export HADOOP_HOME=/export/server/hadoop
export PATH= P A T H : PATH: PATH:HADOOP_HOME/bin:$HADOOP_HOME/sbin
source /etc/profile
chown -R hadoop:hadoop /data
chown -R hadoop:hadoop /export
格式化namenode
#确保以hadoop用户执行
su - hadoop
**<font style="color:rgb(44, 44, 54);">su hadoop</font>**
:不加载目标用户的环境变量和配置文件,适合快速简单的用户切换。**<font style="color:rgb(44, 44, 54);">su - hadoop</font>**
:加载目标用户的环境变量和配置文件,适合需要完整环境配置的情况。
#格式化namenode
hadoop namenode -format
启动
#一键启动hdfs集群
start-dfs.sh
一键关闭hdfs集群
stop-dfs.sh
如果遇到命令未找到的错误,表明环境变量未配置好,可以以绝对路径执行
/export/server/hadoop/sbin/start-dfs.sh
/export/server/hadoop/sbin/stop-dfs.sh
:::danger
快照:hadoop的HDFS部署完成
:::
HDFS集群启停
**一键启停**#一键启动hdfs集群
start-dfs.sh
# 一键关闭hdfs集群
stop-dfs.sh
单进程启停
HDFS文件系统的操作命令
![](https://img-blog.csdnimg/img_convert/e64803cfe53bff72ac8fcb96b2129813.png)使用协议头:
两套命令系统
![](https://img-blog.csdnimg/img_convert/7aac35127b09392b6bad6d538b317501.png)创建文件夹
1. 使用`hadoop fs`命令:hadoop fs -mkdir [-p] <path> ...
- 使用
hdfs dfs
命令:
hdfs dfs -mkdir [-p] <path> ...
<path>
参数表示要创建的新目录的路径。
-p
选项的行为类似于Linux中的mkdir -p
命令,即如果指定的路径包含多级目录,则会递归地创建所有不存在的父目录。
下面是一些具体的示例:
hadoop fs -mkdir -p /itcast/bigdata
hdfs fs -mkdir -p /itheima/hadoop
查看指定目录下的内容
```plain hadoop fs -ls [-h] [-R] [path ...] hdfs dfs -ls [-h] [-R] [path ...] ```-ls
: 列出指定目录的内容。-h
: 人性化显示文件大小,即将字节数转换为更易读的形式(如 KB, MB, GB 等)。-R
: 递归列出目录及其所有子目录的内容。
示例
hadoop fs -ls /user/hadoop/input
hdfs dfs -ls /user/hadoop/input
上传文件到hdfs指定目录下
+ `hadoop fs -put [-f] [-p] ... ` + `hdfs dfs -put [-f] [-p] ... ` + `-f`: 覆盖目标文件。如果目标文件已经存在,使用 `-f` 选项会覆盖已有文件。 + `-p`: 保留属性。保留源文件的权限、所有权和其他元数据。 + ``: 指定要上传的本地文件或目录的路径。 + ``: 指定HDFS中存放文件的目标路径。示例
-
hadoop fs -put words.txt /itcast
: -
将本地文件
words.txt
上传至HDFS的/itcast
目录下。 -
hdfs dfs -put file:///etc/profile hdfs://node1:8020/itcast
: -
将本地文件
/etc/profile
上传至HDFS的node1:8020/itcast
目录下。
查看HDFS文件内容
+ `hadoop fs -cat ...` + `hdfs dfs -cat ...`示例
hadoop fs -cat /itcast/words.txt
:- 显示HDFS中
/itcast/words.txt
文件的所有内容。 hdfs dfs -cat /itcast/words.txt
:- 同样显示HDFS中
/itcast/words.txt
文件的所有内容。
处理大文件
对于较大的文件,直接使用 -cat
可能会导致输出过多,难以阅读。因此结合管道符 |
和 more
命令来分页查看文件内容:
hadoop fs -cat <src> | more
hdfs dfs -cat <src> | more
这里的 more
命令可以让用户逐页查看文件内容,按空格键翻页,按 q
键退出。
下载HDFS文件
+ `hadoop fs -get [-f] [-p] ... ` + `hdfs dfs -get [-f] [-p] ... ` + `-f`: 覆盖目标文件。如果目标文件已经存在,使用 `-f` 选项会覆盖已有文件。 + `-p`: 保留属性。保留源文件的权限、所有权和其他元数据。 + ``: 指定HDFS中要下载的文件或目录的路径。 + ``: 指定本地文件系统中保存文件的目标路径。示例
-
hadoop fs -get /itcast/zookeeper.out ./test
: -
下载HDFS中
/itcast/zookeeper.out
文件到本地文件系统中的./test
目录下。 -
hdfs dfs -get /itcast/zookeeper.out ./test
: -
同样的操作,但使用的是
hdfs dfs
命令。
拷贝HDFS文件
+ `hadoop fs -cp [-f] ... ` + `hdfs dfs -cp [-f] ... `-f
: 覆盖目标文件。如果目标文件已经存在,使用-f
选项会覆盖已有文件。<src>
: 指定HDFS中要复制的文件或目录的路径。<dst>
: 指定HDFS中接收文件的目标路径。
示例
hadoop fs -cp /small/1.txt /itcast
:- 复制HDFS中
/small/1.txt
文件到/itcast
目录下。 hadoop fs -cp /small/1.txt /itcast/666.txt
:- 复制HDFS中
/small/1.txt
文件到/itcast
目录下,并命名为666.txt
。
追加数据到HDFS文件
+ `hadoop fs -appendToFile ... ` + `hdfs dfs -appendToFile ... ` + ``: 指定一个或多个本地文件作为输入,这些文件的内容会被追加到HDFS中的目标文件。 + ``: 指定HDFS中要追加数据的目标文件路径。- 如果
<localsrc>
参数为-
,则从标准输入读取数据。 - 如果
<dst>
文件不存在,命令会先创建该文件再进行追加操作。
示例
echo "Hello World" | hadoop fs -appendToFile - /itcast/file.txt
: 将字符串 “Hello World” 写入标准输入,然后追加到HDFS中/itcast/file.txt
文件的末尾。hadoop fs -appendToFile localfile1.txt localfile2.txt /itcast/combinedfile.txt
: 将本地文件localfile1.txt
和localfile2.txt
的内容追加到HDFS中/itcast/combinedfile.txt
文件的末尾。
HDFS数据移动操作
+ `hadoop fs -mv ... ` + `hdfs dfs -mv ... ` + ``: 指定一个或多个源文件或目录的路径,这些是要被移动的对象。 + ``: 指定目标位置的路径,可以是一个新的文件名(如果是文件的话)或者一个新的目录(如果是整个目录树的话)。:::tips
- 移动文件或目录:将指定的文件或目录从一个位置移到另一个位置。
- 重命名文件:通过改变
<src>
和<dst>
的名称,可以达到重命名文件的目的。 - hadoop fs -mv /test2.txt /itheima/abc.txt
:::
示例
hadoop fs -mv /old/path/to/file /new/path/to/file
: 将文件从/old/path/to/file
移动到/new/path/to/file
。hdfs dfs -mv /old/path/to/directory /new/path/to/directory
: 将目录从/old/path/to/directory
移动到/new/path/to/directory
。
HDFS数据删除操作
+ `hadoop fs -rm -r [-skipTrash] URI [URI ...]` + `hdfs dfs -rm -r [-skipTrash] URI [URI ...]` + `-r`: 表示递归删除,即如果删除对象是目录,则会递归删除该目录及其所有子目录和文件。 + `-skipTrash`: 默认情况下,HDFS会在删除文件时将其移至回收站(.Trash)而非立即永久删除。使用 `-skipTrash` 选项可以直接跳过回收站,立即永久删除文件。 + `URI`: 指定要删除的文件或目录的路径。- 回收站功能默认关闭,若要开启需在
core-site.xml
文件中添加以下配置:
<property>
<name>fs.trash.interval</name>
<value>1440</value>
</property>
这里 fs.trash.interval
设置了回收站在多少分钟后自动清空,默认值为1440分钟(24小时)。
- 此外,还可以配置回收站的检查点间隔时间:
<property>
<name>fs.trash.checkpoint.interval</name>
<value>120</value>
</property>
这里 fs.trash.checkpoint.interval
设置了每隔多少秒检查一次是否有文件需要从回收站清除,默认值为120秒。
示例
hadoop fs -rm -r /path/to/file_or_directory
: 删除指定的文件或目录。hdfs dfs -rm -r -skipTrash /path/to/file_or_directory
: 不经过回收站,直接永久删除指定的文件或目录。
big data tool安装
IED下载插件NFS网关
把HDFS文件部署到win本地磁盘cd /export/server/hadoop/etc/hadoop/
vim core-site.xml
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>nfs.suerpser</name>
<value>hadoop</value>
</property>
<property>
<name>nfs.dump.dir</name>
<value>/tmp/.hdfs-nfs</value>
</property>
<property>
<name>nfs.exports.allowed.hosts</name>
<value>192.168.88.1 rw</value>
</property>
scp core-site.xml hdfs-site.xml node3: pwd
/
停止集群
exit 到root用户
systemctl stop nfs
systemctl disable nfs
yum remove -y rpcbind
hdfs --daemon start portmap
hdfs --daemon start nfs3
启动HDFS集群:start-dfs.sh
net use X: \192.168.88.101!
HDFS副本配置
![](https://img-blog.csdnimg/img_convert/5b86aa0888749c82577037576f3d262a.png)HDFS数据读写流程
![](https://img-blog.csdnimg/img_convert/79d0abe47cf9a51f6abd231547044b23.png)分布式计算MapReduce
![](https://img-blog.csdnimg/img_convert/636ed4538492b587497edd2a06ea2d89.png)MapReduce提供了2个编程接口:
Map
Reduce
其中 Map功能接口提供了“分散”的功能,由服务器分布式对数据进行处理
Reduce功能接口提供了“汇总(聚合)”的功能,将分布式的处理结果汇总统计
用户如需使用MapReduce框架完成自定义需求的程序开发需要使用lava、Python等编程语言,实现Map Reduce功能接口即可。
分布式资源调度YARN
![](https://img-blog.csdnimg/img_convert/a24c46b0550b84ab5c1465063e8bc2ff.png)YARN架构
![](https://img-blog.csdnimg/img_convert/82df9d5d2906da23630cd608ca4f9397.png)MapReduce配置文件
cd /export/server/hadoop/etc/hadoop/vim mapred-env.sh
# 设置JDK路径
export JAVA_HOME=/export/server/jdk
# 设置JobHistoryServer进程内存量为1G
export HADOOP_JOB_HISTORYSERVER_HEAPSIZE=1000
# 设置日志级别为INFO
export HADOOP_MAPRED_ROOT_LOGGER=INFO,RFA
vim mapred-site.xml
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
<description>MapReduce的运行框架设置为 YARN</description>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>node1:10020</value>
<description>历史服务器通讯端口为 node1:10020</description>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>node1:19888</value>
<description>历史服务器web端口为 node1 的 19888</description>
</property>
<property>
<name>mapreduce.jobhistory.intermediate-done-dir</name>
<value>/data/mr-history/tmp</value>
<description>历史信息在HDFS的记录临时路径</description>
</property>
<property>
<name>mapreduce.jobhistory.done-dir</name>
<value>/data/mr-history/done</value>
<description>历史信息在HDFS的记录路径</description>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
<description>MapReduce HOME 设置为 $HADOOP_HOME</description>
</property>
<property>
<name>mapreduce.map.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
<description>MapReduce HOME 设置为 $HADOOP_HOME</description>
</property>
<property>
<name>mapreduce.reduce.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
<description>MapReduce HOME 设置为 $HADOOP_HOME</description>
</property>
YARN部署
![](https://img-blog.csdnimg/img_convert/42c3ae848e670803f9edadd509393985.png)# 设置 JDK 路径的环境变量
export JAVA_HOME=/export/server/jdk
# 设置 HADOOP_HOME 的环境变量
export HADOOP_HOME=/export/server/hadoop
# 设置配置文件路径的环境变量
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
# 设置日志文件路径的环境变量
export HADOOP_LOG_DIR=$HADOOP_HOME/logs
<property>
<name>yarn.resourcemanager.hostname</name>
<value>node1</value>
<description>ResourceManager设置在node1节点</description>
</property>
<property>
<name>yarn.nodemanager.local-dirs</name>
<value>/data/nm-local</value>
<description>NodeManager中间数据本地存储路径</description>
</property>
<property>
<name>yarn.nodemanager.log-dirs</name>
<value>/data/nm-log</value>
<description>NodeManager数据日志本地存储路径</description>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
<description>为MapReduce程序开启Shuffle服务</description>
</property>
<property>
<name>yarn.log.server.url</name>
<value>http://node1:19888/jobhistory/logs</value>
<description>历史服务器URL</description>
</property>
<property>
<name>yarn.web-proxy.address</name>
<value>node1:8089</value>
<description>代理服务器主机和端口</description>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
<description>开启日志聚合</description>
</property>
<property>
<name>yarn.nodemanager.remote-app-log-dir</name>
<value>/tmp/logs</value>
<description>程序日志HDFS的存储路径</description>
</property>
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
<description>选择公平调度器</description>
</property>
scp mapred-env.sh mapred-site.xml yarn-env.sh yarn-site.xml node2:`pwd`/
scp mapred-env.sh mapred-site.xml yarn-env.sh yarn-site.xml node3:`pwd`/
启动:start-yarn.sh
停止:stop-yarn.sh
历史服务器启动:mapred --daemon start historyserver
http://node1:8088
提交MapReduce程序至YARN运行
![](https://img-blog.csdnimg/img_convert/9f8435fcd7dc8296f40363c48037510c.png)cd /export/server/hadoop/share/hadoop/mapreduce
hadoop-mapreduce-examples-3.3.4.jar
- 输入路径:指定数据输入的HDFS(Hadoop Distributed File System)路径。
- 输出路径:指定结果输出的HDFS路径。
- 处理过程:对输入路径内的数据中的单词进行计数,并将结果写入到输出路径。
数据准备:
- 准备一份包含以下内容的数据文件
words.txt
,并上传到HDFS中:
itheima itcast itheima itcast hadoop hdfs hadoop hdfs hadoop mapreduce hadoop yarn itheima hadoop itcast hadoop itheima itcast hadoop yarn mapreduce
HDFS操作命令:
- 创建输入目录
/input/wordcount
:
hadoop fs -mkdir -p /input
- 创建输出目录
/output
:
hadoop fs -mkdir /output
- 将
words.txt
文件上传到HDFS的输入目录:
hadoop fs -put words.txt /input
执行MapReduce程序:
运行以下命令提交WordCount MapReduce程序到YARN执行:
hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.3.4.jar wordcount hdfs://node1:8020/input/ hdfs://node1:8020/output/wc
其中:
- 参数
wordcount
表示运行jar包中的单词计数程序(Java Class)。 - 第一个参数是数据输入路径 (
hdfs://node1:8020/input/wordcount/
)。 - 第二个参数是结果输出路径 (
hdfs://node1:8020/output/wc1
)。
通过这些步骤,可以实现对HDFS中特定路径下的文本文件进行单词计数,并将结果保存在指定的输出路径下。
分布式SQL计算-Hive
![](https://img-blog.csdnimg/img_convert/e596f2de9fb42529d5359ea806cf4e85.png)Hive在虚拟机部署
![](https://img-blog.csdnimg/img_convert/b4fa4d6527551a62ac85bd0ba3801625.png)# 更新密钥
rpm --import https://repo.mysql/RPM-GPG-KEY-mysql-2022
# 安装 MySQL yum 仓库
rpm -Uvh http://repo.mysql/mysql57-community-release-el7-7.noarch.rpm
# 使用 yum 安装 MySQL
yum -y install mysql-community-server
# 启动 MySQL 并设置为开机启动
systemctl start mysqld
systemctl enable mysqld
# 查看 MySQL 服务状态
systemctl status mysqld
# 获取临时密码
grep 'temporary password' /var/log/mysqld.log
#登录
mysql -uroot -p
# 设置密码策略为 LOW
set global validate_password_policy=LOW;
# 设置密码最小长度为 4
set global validate_password_length=4;
# 修改 root 用户密码
ALTER USER 'root'@'localhost' IDENTIFIED BY 'root';
# 授予所有权限
grant all privileges on *.* to 'root'@'%' identified by '123456' with grant option;
# 刷新权限
flush privileges;
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>
su - hadoop
cd /export/server/hadoop/etc/hadoop/
vim core-site.xml
su - hadoop
wget http://archive.apache/dist/hive/hive-3.1.3/apache-hive-3.1.3-bin.tar.gz
tar -zxvf apache-hive-3.1.3-bin.tar.gz -C /export/server/
ln -s /export/server/apache-hive-3.1.3-bin hive
mv mysql-connector-java-5.1.34.jar /export/server/apache-hive-3.1.3-bin/lib/
cd have/conf
mv hive-env.sh.template hive-env.sh
vim hive-env.sh
export HADOOP_HOME=/export/server/hadoop
export HIVE_CONF_DIR=/export/server/hive
export HIVE_AUX_JARS_PATH=/export/server/hive/lib
vim hive-site.xml
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://node1: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>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
</property>
<property>
<name>hive.server2.thrift.bind.host</name>
<value>node1</value>
</property>
<property>
<name>hive.metastore.uris</name>
<value>thrift://node1:9083</value>
</property>
<property>
<name>hive.metastore.event.db.notification.api.auth</name>
<value>false</value>
</property>
</configuration>
CREATE DATABASE hive CHARSET UTF8;
cd /export/server/hive
./bin/schematool -initSchema -dbType mysql -verbos
cd …
cd bin
./schematool -initSchema -dbType mysql -verbos
chown -R hadoop:hadoop apache-hive-3.1.3-bin hive
- 确保Hive文件夹所属为hadoop用户
- 创建一个hive的日志文件文件夹:
mkdir /export/server/hive/logs - 启动元数据管理服务(必须启动,否则无法工作)
前台启动:bin/hive --service metastore
后台启动:nohup bin/hive --service metastore >> logs/metastore.log 2>&1 & - 启动客户端端,二选一(当前先选择Hive Shell方式)
Hive Shell方式(可以直接写SQL):bin/hive
Hive ThriftServer方式(不可以直接写SQL,需要外部客户端链接使用):bin/hive --service hiveserver2
Hive体验执行SQL语句
首先,确保启动了Metastore服务。可以执行:bin/hive,进入到Hive Shell环境中,可以直接执行SQL语句。
- 创建表
CREATE TABLE test(id INT, name STRING, gender STRING);(没有指定数据库,自动创建到default数据库中)
- 插入数据
INSERT INTO test VALUES(1,‘王力红’,‘男’), (2,‘周杰轮’,‘男’), (3,‘林志灵’,‘女’);
- 查询数据
SELECT gender, COUNT(*) AS cnt FROM test GROUP BY gender;
Hive客户端
![](https://img-blog.csdnimg/img_convert/dcc392b2964fe2908b88908e7a03db08.png)HiveServer2服务
![](https://img-blog.csdnimg/img_convert/b8774666dc79cd834f6c41577e966d7b.png)nohup bin/hive --service hiveserver2 >> logs/hiveserver2.log 2>&1 &
beeline
![](https://img-blog.csdnimg/img_convert/03ece57dd5471f43f0d38e56450d5eb2.png)启动:在hive目录输入bin/beeline
连接:!connect jdbc:hive2://node1:10000
输入用户名hadoop,密码跳过
Hive语法
数据库操作
创建数据库
create database if not exists myhive;use myhive;
• 查看数据库详细信息
desc database myhive;
- 创建数据库并指定HDFS存储位置
create database myhive storage location '/myhive';
使用location关键字,可以指定数据库在HDFS上的存储路径。
删除数据库
+ 删除一个空数据库,如果数据库下面有数据表,那么就会报错drop database myhive;
- 强制删除数据库,包含数据库下面的表一起删除
drop database myhive cascade;
创建数据库表
```sql 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 row_format] [STORED AS file_format] [LOCATION hdfs_path] ```- EXTERNAL, 创建外部表
- PARTITIONED BY, 分区表
- CLUSTERED BY, 分桶表
- STORED AS, 存储格式
- LOCATION, 存储位置
内部表/外部表
在 Apache Hive 中,表可以分为两种类型:内部表(Managed Tables)和外部表(External Tables)。这两种表在管理和数据删除方面有一些重要的区别。内部表(Managed Tables)
- 定义:
- 内部表是由 Hive 完全管理的数据表。
- 当你创建一个内部表时,Hive 会在默认的仓库目录(通常是
hdfs://<namenode>:<port>/user/hive/warehouse
)下创建一个子目录来存储表的数据。
- 创建语法:
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
...
)
[PARTITIONED BY (column3 datatype, ...)]
[CLUSTERED BY (column4, ...) SORTED BY (column5) INTO num_buckets BUCKETS]
[ROW FORMAT DELIMITED FIELDS TERMINATED BY 'char']
[STORED AS file_format]
[LOCATION hdfs_path];
- 数据存储:
- 默认情况下,数据存储在 Hive 的仓库目录下的一个子目录中。
- 例如,如果你创建一个名为
employees
的表,数据将存储在hdfs://<namenode>:<port>/user/hive/warehouse/employees
目录下。
- 数据删除:
- 当你删除一个内部表时,Hive 不仅会删除表的元数据,还会删除表对应的数据文件。
- 例如:
DROP TABLE employees;
这条命令会删除 employees
表及其所有数据。
外部表(External Tables)
- 定义:
- 外部表是指数据存储在 Hive 仓库目录之外的表。
- 创建外部表时,你需要指定数据的实际存储位置。
- 创建语法:
CREATE EXTERNAL TABLE table_name (
column1 datatype,
column2 datatype,
...
)
[PARTITIONED BY (column3 datatype, ...)]
[CLUSTERED BY (column4, ...) SORTED BY (column5) INTO num_buckets BUCKETS]
[ROW FORMAT DELIMITED FIELDS TERMINATED BY 'char']
[STORED AS file_format]
LOCATION 'hdfs_path'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
LOCATION '/tmp/test/test_extl1';
- 数据存储:
- 数据存储在你指定的 HDFS 路径下。
- 例如,如果你创建一个名为
external_employees
的外部表,并指定数据存储在/user/data/external_employees
目录下:
CREATE EXTERNAL TABLE external_employees (
id INT,
name STRING,
department STRING
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
STORED AS TEXTFILE
LOCATION '/user/data/external_employees';
- 数据删除:
- 当你删除一个外部表时,Hive 只会删除表的元数据,而不会删除表对应的数据文件。
- 例如:
DROP TABLE external_employees;
这条命令只会删除 external_employees
表的元数据,而不会删除存储在 /user/data/external_employees
目录下的数据文件。
总结
- 内部表:数据由 Hive 管理,删除表时会删除数据。因此内部表不适合和其他工具共享数据。
- 外部表:数据存储在指定的 HDFS 路径,删除表时只删除元数据,保留数据。
相互转换
hive数据的导入和导出
![](https://img-blog.csdnimg/img_convert/c9861e71e37f9979613a61c089a74eff.png)我们使用 LOAD 语法,从外部将数据加载到Hive内,语法如下:
LOAD DATA [LOCAL] INPATH ‘filepath’ [OVERWRITE] INTO TABLE tablename;
1:上传数据文件到Linux系统
2:创建表
CREATE TABLE myhive.test_load_load(
dt string COMMENT '时间(时分秒)',
user_id string COMMENT '用户ID',
word string COMMENT '搜索词',
url string COMMENT '用户访问网址'
) COMMENT '搜索引擎日志表'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
3:数据加载
load data local inpath '/home/hadoop/search_log.txt' [overwrite] into table myhive.test_load_load;
Hive 从Linux本地文件系统加载数据。关键字 <font style="color:rgb(44, 44, 54);">local</font>
表示数据源是在本地文件系统上的。
load data inpath '/tmp/search_log.txt' overwrite into table myhive.test_load;
Hive 从 HDFS 加载数据。源数据文件会消失(本质是被移动到表所在的目录中)
分区表
![](https://img-blog.csdnimg/img_convert/f7b56d5dddf628a3b5abd3c3289bbe95.png)。
分区表的概念
分区表是将表的数据按照一个或多个列的值分成多个部分,每个部分称为一个分区。每个分区可以存储在一个独立的目录中,这样在查询时可以根据分区条件快速定位到所需的数据。
创建分区表
单分区表
假设我们有一个日志表 `logs`,我们希望按日期进行分区。可以使用以下 SQL 语句创建单分区表:CREATE TABLE logs (
id INT,
message STRING
)
PARTITIONED BY (dt STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
在这个例子中,dt
列用于分区,每个分区将存储在不同的目录中。
多分区表
如果需要按多个列进行分区,可以使用多个 `PARTITIONED BY` 列。例如,按日期和小时进行分区:CREATE TABLE logs (
id INT,
message STRING
)
PARTITIONED BY (dt STRING, hr STRING)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t';
查询分区表
查询分区表时,可以通过指定分区条件来提高查询效率。例如:SELECT * FROM logs WHERE dt = '2023-10-01';
删除分区
可以使用 `ALTER TABLE` 语句删除分区:ALTER TABLE logs DROP PARTITION (dt = '2023-10-01');
分桶表
分桶概念(Bucketing)
分桶是 Hive 中一种用于优化查询的技术,它通过将数据按照某个列的值进行哈希散列,并根据散列值将数据分布到多个文件中,这些文件被称为“桶”。每个桶可以看作是一个小的数据集,这样可以使得在处理大规模数据集时更加高效,尤其是在进行连接操作或者采样时。优点
- 提升查询效率:当需要对特定列进行过滤或聚合时,分桶可以减少需要扫描的数据量,从而加快查询速度。
- 并行处理:由于数据已经被均匀地分配到了不同的桶中,因此可以更容易地实现并行处理。
- 采样:对于大数据集,如果数据已经均匀地分布在各个桶中,那么从每个桶中抽取少量数据就可以得到一个代表性的样本,这对于数据探索和分析非常有用。
缺点
- 增加数据准备时间:创建分桶表时,需要额外的时间来计算哈希值并将数据正确地放入相应的桶中。
- 桶的数量选择:需要合理选择桶的数量,太少会导致数据倾斜,太多则可能增加存储开销和管理复杂度。
创建分桶表
在创建分桶表时,通常会指定一个或多个列作为分桶列,并指定桶的数量。例如,假设我们有一个用户行为日志表,我们希望基于用户的 `user_id` 进行分桶,可以这样创建表:set hive.enforce.bucketing=true;
CREATE TABLE user_behavior (
user_id INT,
action STRING,
time TIMESTAMP
)
CLUSTERED BY (user_id) INTO 32 BUCKETS
row format delimited fields terminated by '\t';
这里,CLUSTERED BY (user_id)
指定了分桶列,而 INTO 32 BUCKETS
则指定了将数据分为32个桶。
加载数据到分桶表
![](https://img-blog.csdnimg/img_convert/aacd87cf13aa3a5227dffa581edd197a.png)修改表的sql操作
1. 修改表注释
```sql ALTER TABLE table_name SET TBLPROPERTIES ('comment' = 'new_comment'); ```table_name
是你想要修改的表的名字,new_comment
是新的注释信息。
2. 表重命名
```sql ALTER TABLE old_table_name RENAME TO new_table_name; ```old_table_name
是当前表的名字,new_table_name
是新名字。
3. 添加列
```sql ALTER TABLE table_name ADD COLUMNS (column_name column_type [COMMENT 'column_comment']); ```table_name
是你要添加列的表的名字,column_name
是新列的名字,column_type
是新列的数据类型,可选的 COMMENT
用来提供列的说明。
4. 修改列名
```sql ALTER TABLE table_name CHANGE COLUMN old_column_name new_column_name column_type [COMMENT 'column_comment']; ```old_column_name
是旧列名,new_column_name
是新列名,column_type
是列的新数据类型,COMMENT
是可选的列说明。
5. 删除表
```sql DROP TABLE IF EXISTS table_name; ```IF EXISTS
是可选的,但建议加上,以防表不存在时出错。
6. 清空表
清除表中的所有数据,但保留表结构,无法清空外部表TRUNCATE TABLE table_name;
请注意,TRUNCATE 不同于 DELETE,因为它不会触发任何触发器,而且它的执行速度更快。
7.添加分区
使用 ` ALTER TABLE ... ADD PARTITION` 语句。例如,假设有一个按日期分区的表 ` web_logs` ,你可以这样添加一个新的分区:ALTER TABLE web_logs ADD PARTITION (dt='2024-01-01') LOCATION '/user/hive/warehouse/web_logs/dt=2024-01-01';
<font style="color:rgb(44, 44, 54);">dt</font>
是分区列,<font style="color:rgb(44, 44, 54);">2024-01-01</font>
是分区值,<font style="color:rgb(44, 44, 54);">LOCATION</font>
指定了分区数据在 HDFS 上的存储路径。如果不指定 <font style="color:rgb(44, 44, 54);">LOCATION</font>
,Hive 会默认在表的目录下创建一个子目录来存储该分区的数据。
8.删除分区
会删除hive里面的元数据,但是不会删除hdfs里面的数据文件。ALTER TABLE web_logs DROP PARTITION (dt='2024-01-01');
array数组
![](https://img-blog.csdnimg/img_convert/6af82229d97b1530a426278be651966e.png)可以使用array数组类型,存储locations的数据,要求数据类型一致
CREATE TABLE myhive.test_array(
name STRING,
work_locations ARRAY<STRING>
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t'
COLLECTION ITEMS TERMINATED BY ',';
SELECT id, name, courses[0] AS first_course FROM stu
SELECT id, name, size(courses) AS num_courses FROM students;
SELECT id, name, array_contains(courses, 'Math') AS has_math FROM students;
map映射
![](https://img-blog.csdnimg/img_convert/56bb972cedb2ba2359ea4ca356f99b43.png)create table myhive.test_map(
id int,
name string,
members map<string,string>,
age int
)
row format delimited
fields terminated by ','
COLLECTION ITEMS TERMINATED BY '#'
MAP KEYS TERMINATED BY ':';
select
id,
name,
members['father'],
members['mother']
from
myhive.test_map;
select
map_keys(members)
from
myhive.test_map;
-- ,看看谁有 sister 这个 key
SELECT *
FROM myhive.test_map
WHERE ARRAY_CONTAINS(map_keys(members), 'sister');
SELECT *
FROM myhive.test_map
WHERE ARRAY_CONTAINS(map_values(members), '王林');
struct数据类型
![](https://img-blog.csdnimg/img_convert/b3dee2bd1b6dba2d31d50ce9ec59ee9f.png) ![](https://img-blog.csdnimg/img_convert/6a8aba61c77010e986fea76751548589.png)CREATE TABLE myhive.test_struct (
id STRING,
info STRUCT<name:STRING, age:INT>
)#info是struct的整体列名
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '#'
COLLECTION ITEMS TERMINATED BY ':';
SELECT id, info.name, info.age
FROM myhive.test_struct;
基本查询
**1. SELECT 语句**SELECT
语句用于从表中选择数据。基本语法如下:
SELECT column1, column2, ...
FROM table_name;
2. 聚合函数
聚合函数用于对一组值进行计算并返回单个值。常见的聚合函数包括:
COUNT(*)
:计算行数。COUNT(column)
:计算指定列的非空值数量。SUM(column)
:计算指定列的总和。AVG(column)
:计算指定列的平均值。MIN(column)
:计算指定列的最小值。MAX(column)
:计算指定列的最大值。
-- 计算表中所有行的数量
SELECT COUNT(*) FROM sales;
-- 计算销售额的总和
SELECT SUM(amount) FROM sales;
-- 计算平均销售额
SELECT AVG(amount) FROM sales;
-- 计算最小和最大销售额
SELECT MIN(amount), MAX(amount) FROM sales;
3. GROUP BY 子句
GROUP BY
子句用于将数据分组,通常与聚合函数一起使用。语法如下:
SELECT column1, aggregate_function(column2)
FROM table_name
GROUP BY column1;
-- 按产品类别分组,计算每个类别的销售总额
SELECT category, SUM(amount) AS total_sales
FROM sales
GROUP BY category;
-- 按客户分组,计算每个客户的订单数量
SELECT customer, COUNT(order_id) AS order_count
FROM orders
GROUP BY customer;
4. JOIN 子句
JOIN
子句用于将多个表中的数据组合在一起。常见的 JOIN
类型包括:
INNER JOIN
:返回两个表中匹配的行。LEFT JOIN
:返回左表中的所有行,以及右表中匹配的行。如果没有匹配的行,则返回 NULL。RIGHT JOIN
:返回右表中的所有行,以及左表中匹配的行。如果没有匹配的行,则返回 NULL。FULL OUTER JOIN
:返回两个表中的所有行,如果没有匹配的行,则返回 NULL。
-- INNER JOIN 示例
SELECT o.order_id, o.customer, p.product_name, o.amount
FROM orders o
INNER JOIN products p ON o.product_id = p.product_id;
-- LEFT JOIN 示例
SELECT o.order_id, o.customer, p.product_name, o.amount
FROM orders o
LEFT JOIN products p ON o.product_id = p.product_id;
-- RIGHT JOIN 示例
SELECT o.order_id, o.customer, p.product_name, o.amount
FROM orders o
RIGHT JOIN products p ON o.product_id = p.product_id;
-- FULL OUTER JOIN 示例
SELECT o.order_id, o.customer, p.product_name, o.amount
FROM orders o
FULL OUTER JOIN products p ON o.product_id = p.product_id;
5. ORDER BY 子句
ORDER BY
子句用于对查询结果进行排序。语法如下:
SELECT column1, column2, ...
FROM table_name
ORDER BY column1 [ASC | DESC], column2 [ASC | DESC], ...;
-- 按销售额降序排列
SELECT customer, SUM(amount) AS total_sales
FROM sales
GROUP BY customer
ORDER BY total_sales DESC;
-- 按客户升序排列,按订单日期降序排列
SELECT customer, order_date, amount
FROM orders
ORDER BY customer ASC, order_date DESC;
正则表达式
![](https://img-blog.csdnimg/img_convert/15abeedf416088b4bad7cda556beef15.png):::color2
.中是对.的进一步解释,两个符号不是独立的存在
:::
union联合
union用于将多个select语句的结果组合成单个结果集。 每个select语句返回的列的数量和名称必须相同。否则,将引发架构错误。- UNION:合并结果集并去除重复行。
- UNION ALL:合并结果集并保留所有行,包括重复的行。
SELECT column1, column2, ...
FROM table1
UNION
SELECT column1, column2, ...
FROM table2
[UNION
SELECT column1, column2, ...
FROM table3]
...
采样(Sampling)
![](https://img-blog.csdnimg/img_convert/a889668f56a6d2646f3bd5854ccc5c75.png)1. 基于行的采样
基于行的采样使用 `TABLESAMPLE` 关键字,可以通过指定百分比或行数来抽取样本。SELECT *
FROM table_name
TABLESAMPLE (type AND expression);
按百分比采样
-- 抽取表中 10% 的行
SELECT *
FROM sales
TABLESAMPLE (10 PERCENT);
按行数采样
-- 抽取表中 1000 行
SELECT *
FROM sales
TABLESAMPLE (1000 ROWS);
2. 埋点采样(Bucket Sampling)
基于桶的采样是一种更精确的采样方法,它将数据分成多个桶,然后从每个桶中抽取样本。这种方法适用于大数据集,可以确保样本的均匀分布。x
:要抽取的桶编号。y
:总的桶数。- colname指代列名,表示根据给出的列名把数据分成y个桶,rand()表示把数据随机分桶。
假设我们有一个表 sales
,我们想从该表中抽取 1/10 的数据。
-- 将数据分成 10 个桶,抽取第 1 个桶的数据
SELECT *
FROM sales
TABLESAMPLE (BUCKET 1 OUT OF 10 ON date);
3. 随机采样
Hive 还支持使用随机函数进行采样。可以使用 `RAND()` 函数来抽取随机样本。-- 抽取表中随机的 10% 的行
SELECT *
FROM sales
WHERE RAND() <= 0.1;
虚拟列
![](https://img-blog.csdnimg/img_convert/e6a89fa9a8215a74fcd5827f6b31df70.png)案例
需求分析
建库建表
```sql --如果数据库已存在就删除 drop database if exists db_msg cascade ; --创建数据库 create database db_msg ; --切换数据库 use db_msg ; ```--建表
CREATE TABLE db_msg.tb_msg_source(
msg_time STRING COMMENT "消息发送时间",
sender_name STRING COMMENT "发送人昵称",
sender_account STRING COMMENT "发送人账号",
sender_sex STRING COMMENT "发送人性别",
sender_ip STRING COMMENT "发送人IP地址",
sender_os STRING COMMENT "发送人操作系统",
sender_phonetype STRING COMMENT "发送人手机型号",
sender_network STRING COMMENT "发送人网络类型",
sender_gps STRING COMMENT "发送人的GPS定位",
receiver_name STRING COMMENT "接收人昵称",
receiver_ip STRING COMMENT "接收人IP",
receiver_account STRING COMMENT "接收人账号",
receiver_os STRING COMMENT "接收人操作系统",
receiver_phonetype STRING COMMENT "接收人手机型号",
receiver_network STRING COMMENT "接收人网络类型",
receiver_gps STRING COMMENT "接收人的GPS定位",
receiver_sex STRING COMMENT "接收人性别",
msg_type STRING COMMENT "消息类型",
distance STRING COMMENT "双方距离",
message STRING COMMENT "消息内容"
);
- 数据文件上传到/home/hadoop,上传数据文件
- 创建hadoop文件夹,上传数据文件到hdfs
hadoop fs -mkdir -p /chatdemo/data
hadoop fs -put chat_data-5W.csv /chatdemo/data/
- 加载数据到表中
load data inpath '/chatdemo/data/chat_data-30W.csv' into table tb_msg_source;
ETL数据清洗
![](https://img-blog.csdnimg/img_convert/83b05bee47b0ac5c414000e859ad6dde.png)
// 创建新表
CREATE TABLE db_msg.tb_msg_etl(
msg_time STRING COMMENT "消息发送时间",
sender_name STRING COMMENT "发送人昵称",
sender_account STRING COMMENT "发送人账号",
sender_sex STRING COMMENT "发送人性别",
sender_ip STRING COMMENT "发送人IP地址",
sender_os STRING COMMENT "发送人操作系统",
sender_phonetype STRING COMMENT "发送人手机型号",
sender_network STRING COMMENT "发送人网络类型",
sender_gps STRING COMMENT "发送人的GPS定位",
receiver_name STRING COMMENT "接收人昵称",
receiver_ip STRING COMMENT "接收人IP",
receiver_account STRING COMMENT "接收人账号",
receiver_os STRING COMMENT "接收人操作系统",
receiver_phonetype STRING COMMENT "接收人手机型号",
receiver_network STRING COMMENT "接收人网络类型",
receiver_gps STRING COMMENT "接收人的GPS定位",
receiver_sex STRING COMMENT "接收人性别",
msg_type STRING COMMENT "消息类型",
distance STRING COMMENT "双方距离",
message STRING COMMENT "消息内容"
msg_day string comment "消息日",
msg_hour string comment "消息小时",
sender_lng double comment "经度",
sender_lat double comment "纬度"
);
SELECT
msg_time AS msg_time,
DATE(msg_time) AS msg_day,
*,
HOUR(msg_time) AS msg_hour,
SPLIT(sender_gps, ',')[0] AS sender_lng,
SPLIT(sender_gps, ',')[1] AS sender_lat
FROM db_msg.tb_msg_source
WHERE LENGTH(sender_gps) > 0;
指标计算
![](https://img-blog.csdnimg/img_convert/ed8c8c387a92383c0b0500880d58f286.png)// 统计今日消息总量
CREATE TABLE db_msg.tb_rs_total_msg_cnt COMMENT '每日消息总量' AS
SELECT msg_day, COUNT(*) AS total_msg_cnt FROM db_msg.tb_msg_etl GROUP BY msg_day;
-- 需求2:统计每小时的消息量、发送和接受的用户数量
create table db_msg.tb_rs_hour_msg_cnt comment '每小时消息量趋势' as
SELECT
msg_hour,
COUNT(*) AS total_msg_cnt,
COUNT(DISTINCT sender_account) AS sender_user_cnt,
COUNT(DISTINCT receiver_account) AS receiver_user_cnt
FROM db_msg.tb_msg_etl
GROUP BY msg_hour;
-- 统计今日各地区发送消息总数量
CREATE TABLE db_msg.tb_rs_loc_cnt
COMMENT '今日各地区发送消息总数量'
AS
SELECT
msg_day,
sender_lng,
sender_lat,
COUNT(*) AS total_msg_cnt
FROM db_msg.tb_msg_etl
GROUP BY msg_day, sender_lng, sender_lat;
-- 统计今日发送和接收用户的数量
CREATE TABLE db_msg.tb_rs_user_cnt
COMMENT '每日发送和接收消息的人数'
AS
SELECT
msg_day,
COUNT(DISTINCT sender_account) AS sender_user_cnt,
COUNT(DISTINCT receiver_account) AS receiver_user_cnt
FROM db_msg.tb_msg_etl
GROUP BY msg_day;
-- 统计发送消息最多的Top10用户
CREATE TABLE db_msg.tb_rs_s_user_top10
COMMENT '发送消息最多的10个用户'
AS
SELECT
sender_name,
COUNT(*) AS sender_msg_cnt
FROM db_msg.tb_msg_etl
GROUP BY sender_name
ORDER BY sender_msg_cnt DESC
LIMIT 10;
-- 统计接收消息最多的Top10用户
CREATE TABLE db_msg.tb_rs_r_user_top10
COMMENT '接收消息最多的10个用户'
AS
SELECT
receiver_name,
COUNT(*) AS receiver_msg_cnt
FROM db_msg.tb_msg_etl
GROUP BY receiver_name
ORDER BY receiver_msg_cnt DESC
LIMIT 10;
-- 统计发送人的手机型号分布情况
CREATE TABLE db_msg.tb_rs_sender_phone
COMMENT '发送人的手机型号分布'
AS
SELECT
sender_phonetype,
COUNT(*) AS cnt
FROM db_msg.tb_msg_etl
GROUP BY sender_phonetype;
-- 统计发送人的手机操作系统分布情况
CREATE TABLE db_msg.tb_rs_sender_os
COMMENT '发送人的手机型号分布'
AS
SELECT
sender_os,
COUNT(*) AS cnt
FROM db_msg.tb_msg_etl
GROUP BY sender_os;
可视化展现
![](https://img-blog.csdnimg/img_convert/eb7357ddd0444ec3f84e69ccbea4e7d9.png)激活码: