目录
环境安装搭建
编写同步集群脚本以及查看集群进程脚本
MySQL
Hadoop
Hadoop UI
HDFS 存储
MapReduce 计算
Yarn 资源管理
HBase
HBase基本操作
HBase运维和优化
ZooKeeper
Hive
Hive基本操作
Hive SQL大全
Hive运维管理
Hive备份与恢复
Hive参数调优
Impala & Presto
Sqoop
Spark
感谢公司资助的大数据企业实战培训,我把内容记录整理了一下,希望能帮到大家。此文是大数据常见开源组件的介绍。如果觉得一个个组件安装麻烦,可以安装CDH,关于CDH可参考我的另一篇文章:https://blog.csdn.net/Beth_Chan/article/details/111176053
1. Create CentOS server and clone 3 servers
2. vi /etc/sysconfig/network
hadoop01
3. vi /etc/sysconfig/network-scripts/ifcfg-ens33
Config static IP等
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
DEVICE=ens33
ONBOOT=yes
IPADDR=172.16.235.134
GATEWAY=172.16.235.2
NETMASK=255.255.255.0
DNS1=8.8.8.8
4. vi /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.235.134 hadoop01
172.16.235.135 hadoop02
172.16.235.136 hadoop03
5. Verify the network connection
[root@hadoop01 ~]# ping hadoop01
PING hadoop01 (172.16.235.134) 56(84) bytes of data.
64 bytes from hadoop01 (172.16.235.134): icmp_seq=1 ttl=64 time=0.041 ms
64 bytes from hadoop01 (172.16.235.134): icmp_seq=2 ttl=64 time=0.072 ms
64 bytes from hadoop01 (172.16.235.134): icmp_seq=3 ttl=64 time=0.116 ms
^C
--- hadoop01 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.041/0.076/0.116/0.031 ms
[root@hadoop01 ~]# ping hadoop02
PING hadoop02 (172.16.235.135) 56(84) bytes of data.
64 bytes from hadoop02 (172.16.235.135): icmp_seq=1 ttl=64 time=0.674 ms
64 bytes from hadoop02 (172.16.235.135): icmp_seq=2 ttl=64 time=0.382 ms
64 bytes from hadoop02 (172.16.235.135): icmp_seq=3 ttl=64 time=0.566 ms
^C
--- hadoop02 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2006ms
rtt min/avg/max/mdev = 0.382/0.540/0.674/0.123 ms
[root@hadoop01 ~]# ping hadoop03
PING hadoop03 (172.16.235.136) 56(84) bytes of data.
64 bytes from hadoop03 (172.16.235.136): icmp_seq=1 ttl=64 time=0.680 ms
64 bytes from hadoop03 (172.16.235.136): icmp_seq=2 ttl=64 time=0.749 ms
64 bytes from hadoop03 (172.16.235.136): icmp_seq=3 ttl=64 time=0.555 ms
^C
--- hadoop03 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 0.555/0.661/0.749/0.082 ms
6. ssh免密登录
(1) ssh-keygen
(一直按回车即可)
会生成一对公钥和密钥,/root/.ssh文件夹下,id_rsa就是本机的密钥,id_rsa.pub就是公钥
(2) ssk-copy-id 其它节点的IP地址
(如有提示yes/no,则yes,需要密码则输入用户密码,完成后exit退回来)
(注意需要ssh-copy-id 自己的IP地址,以及127.0.0.1,就可以不用输入自己本机的密码)
在机子上分别ssh-copy-id hadoop01; ssh-copy-id hadoop02; ssh-copy-id hadoop03
ssh hadoop01 (可验证不用密码)
ssh hadoop02
ssh hadoop03
详情如下:
[root@hadoop01 ~]# ll .ssh
total 12
-rw-------. 1 root root 1675 Aug 20 21:13 id_rsa
-rw-r--r--. 1 root root 395 Aug 20 21:13 id_rsa.pub
-rw-r--r--. 1 root root 370 Aug 20 21:16 known_hosts
[root@hadoop01 ~]# cd .ssh
[root@hadoop01 .ssh]# cat id_rsa
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAvmD8QHrBqYXzjoufOnWHLD1LVUrp7JA6YNIeBIO1JUFGW/2C
NEkt2mS93urkXv779tEcAxEqvuT25exFizamPkSZpiqFMf8BiHvDl8ib+lqywfdA
PZlsYQSd0SvO6oER6rkCuBGQQwwWWUjC3D+4FHxGUyHgT63IxVNypvyNP+tQyYAF
E2pJMTULm5gtttYGdJxwNLMJgj0Ujz6Yr8cV2sn2eGHaWJLK6Hu4/3z8ERb69srh
7/J53wxR3PIakvps8GqeZ5pHi7gfqyspGeFXFKa+EOZBfZU1cJv9cHOt3Rwk8fM3
ke0xQP28AkqUp95Z+0cM/BNzGdXxz/pi7J5daQIDAQABAoIBAH9/EDBWha/0R2Jl
WyOZZgdYnUTnwLVu+cmxrey0D/J9PpOIuVQu1gh2gznw8TQ1a6Sl8i6Tpp7lU/wz
OXe8B6WX55aCz2TmNK6kxB64eM03RJPl9B3My+pFXzOgNRiTi944PPvst0JPq//r
XKSH/82oVKiD/WcfKWANPLFcXXQ6B+WSYG9+Y+7BsdFCHlPvwTSdcZh0hL/Btbe3
FsBYUbysympvMCdvOTTgNY8aLcmpRxGwWQ4RcjxmPdaT+wdqtni5Qf+usDbah/D6
j7NCISHVyRM4gl/zEfKZ/wAeq4pNeuEy13H5Wd6OHvZQAWZpelc9lpS6IrlD1FJa
HVNjgQECgYEA934Vs9KZ60oui2SvfDTRvouBUCGsQKeU6cgUYfyRx1sQPCI2sk9G
PGFEJNUvjccQEjyRxQBLdspxNt1cp3vbn/v4WX4fZDz9LQ8YfdjL2SEmb7w0DXrr
e8OFA+QNyg7dtHz5r9ycAmSf62BS1F64xn1IX04EN7idTg4cWCVLOnECgYEAxOxN
/lLeCspghTakGj2cDe5FHrXFiEKv+XKkuOn4vR4JCRJe760xEavlnT669wWRRQf3
L9H47POu15cVxc1rRM9ODiAPHFfNPA8FqG6mhvgFpjmHjm1e7TFpgr77Tc37NzLV
MyzTZ//FekgsLXv64zjLm5i1GHrh1sIHMzDennkCgYEAgXRKFc1LBW+/+NmpkOZv
76M4+JkkaI0/rykgwEBEYGqZi1q6EXq12k9mPX3ladt95IwaE1mcH360yWXwWQrI
Tl6WAPmfoebk5vTGcs07k09rs3ZWI9bv5cTXhrl7HP25qfbVA8/5KqdHnu67ZKpH
LEvL104PlrXSUkm/ObwIJYECgYBWrm3mdTOoLE0wVk0F//ihaTCjw/+faztq4jv/
6X3EQWRYye1gMyxWSwRXozVJZvn7GPaF5jdclidwXuEGoNWHBHmnXhVItJ1ywmoL
KinDX4mdEdXJq/sNDaMUGl0kcncSZR3T2Pd13/BdU0ee/eQCAQ4e/6k3jV+72Myy
i+BygQKBgFhNi6HLWj0XmpdspyxLARtoFfe2z7WkgPEBF/jFU4wNW0TOkvWrXXnG
vs97agdvqMd64YHURYXmaRZ/iC6fZ3YS7EkBnPPnVRZFfnoISA8ig4PfYsc10WV+
u2urH6hcayGyqb2gJrpHvymBa//RrnF6Q8qNcGxvCJei8/RmiR9W
-----END RSA PRIVATE KEY-----
[root@hadoop01 .ssh]# cat id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+YPxAesGphfOOi586dYcsPUtVSunskDpg0h4Eg7UlQUZb/YI0SS3aZL3e6uRe/vv20RwDESq+5Pbl7EWLNqY+RJmmKoUx/wGIe8OXyJv6WrLB90A9mWxhBJ3RK87qgRHquQK4EZBDDBZZSMLcP7gUfEZTIeBPrcjFU3Km/I0/61DJgAUTakkxNQubmC221gZ0nHA0swmCPRSPPpivxxXayfZ4YdpYksroe7j/fPwRFvr2yuHv8nnfDFHc8hqS+mzwap5nmkeLuB+rKykZ4VcUpr4Q5kF9lTVwm/1wc63dHCTx8zeR7TFA/bwCSpSn3ln7Rwz8E3MZ1fHP+mLsnl1p root@hadoop01
[root@hadoop01 .ssh]# cat known_hosts
hadoop02,172.16.235.135 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPYI6UHkpAVRMQKeG5adfF6M6/6mKaOcThwjBfj2swi61xZUCmE6QR7BGeaYrVsfRg1Rz5LZMNnKUfOkpOaQsT8=
hadoop03,172.16.235.136 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPYI6UHkpAVRMQKeG5adfF6M6/6mKaOcThwjBfj2swi61xZUCmE6QR7BGeaYrVsfRg1Rz5LZMNnKUfOkpOaQsT8=
[root@hadoop02 ~]# ll .ssh
total 8
-rw-------. 1 root root 395 Aug 20 21:14 authorized_keys
-rw-r--r--. 1 root root 370 Aug 20 21:16 known_hosts
[root@hadoop02 ~]# cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+YPxAesGphfOOi586dYcsPUtVSunskDpg0h4Eg7UlQUZb/YI0SS3aZL3e6uRe/vv20RwDESq+5Pbl7EWLNqY+RJmmKoUx/wGIe8OXyJv6WrLB90A9mWxhBJ3RK87qgRHquQK4EZBDDBZZSMLcP7gUfEZTIeBPrcjFU3Km/I0/61DJgAUTakkxNQubmC221gZ0nHA0swmCPRSPPpivxxXayfZ4YdpYksroe7j/fPwRFvr2yuHv8nnfDFHc8hqS+mzwap5nmkeLuB+rKykZ4VcUpr4Q5kF9lTVwm/1wc63dHCTx8zeR7TFA/bwCSpSn3ln7Rwz8E3MZ1fHP+mLsnl1p root@hadoop01
7. 安装JDK
(1) Create a folder to put the installation packages, all program folders will be put into the /usr/local
(2) tar -zxvf to unzip, mv to change the names
(3) vim /etc/profile
export execution variables
eg: for JDK
export JAVA_HOME=/usr/java/jdk1.8.0_121
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
使其生效:
source /etc/profile
java -version
8. sftp本地的文件到虚拟机上
[root@hadoop01 local]# sftp hadoop01
Connected to hadoop01.
sftp> put '//tmp/VMwareDnD/m71hVa/sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz' /usr/local
Uploading //tmp/VMwareDnD/m71hVa/sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz to /usr/local/sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz
//tmp/VMwareDnD/m71hVa/sqoop-1.4.6.bin__hadoop-2.0.4 100% 16MB 70.1MB/s 00:00
sftp> exit
[root@hadoop01 local]# ls
bin flume hadoop hive.bak jdk lib libexec presto sbin software yanagishima
etc games hbase include kafka lib64 mysql python26 share src zookeeper
9. 修改Hadoop configurations
修改JAVA_HOME的地址
fs.default.name
hdfs://hadoop01:9000
hadoop.tmp.dir
/usr/local/hadoop/tmp
Abase for other temporary directories.
dfs.replication
3
dfs.namenode.secondary.http-address
hadoop02:50090
(可保持默认,暂时不修改)
(可保持默认,暂时不修改)
10. 修改好配置后即可启动
start-all.sh 或者单独启动 hdfs, yarn
jps 查看进程是否正确
Sync folders and files to other servers
(1) Sync jdk & execution variables singlely is too troublesome:
scp -r /usr/local/jdk hadoop02:/usr/local
scp /etc/profile hadoop02:/etc/profile
(2) Script to sync cluster's folders or files:
xsync.sh
#!/bin/bash
# $#:表示传递给脚本或函数的参数个数。
#1 获取输入参数个数,如果没有参数,直接退出
pcount=$#
if((pcount==0)); then
echo no args;
exit;
fi
#2 获取文件名称
p1=$1
fname=`basename $p1`
echo fname=$fname
#3 获取上级目录到绝对路径
pdir=`cd -P $(dirname $p1); pwd`
echo pdir=$pdir
#4 获取当前用户名称
user=`whoami`
#5 循环
for((host=01; host<04; host++)); do
echo ------------------- hadoop$host --------------
rsync -rvl $pdir/$fname $user@hadoop0$host:$pdir
Done
其中 rsync -rvl $pdir/$fname $user@hadoop0$host:$pdir 中的 rsync,remote sync,只传送source和destination的不同部分。-r表示递归,-v表示输出详细信息,-l表示保留软连接,可参考阅读: https://man.linuxde.net/rsync,https://www.ruanyifeng.com/blog/2020/08/rsync.html
执行以下命令:
chmod 777 xysnc.sh
xsync.sh /usr/local/jdk
xsync.sh /etc/profile
即可同步/usr/local/jdk和/etc/profile里的变量设置到集群里的其他servers
(3) Review Cluster's process
xcall.sh
#! /bin/bash
for i in hadoop01 hadoop02 hadoop03
do
echo --------- $i ----------
ssh $i "$*"
done
执行以下命令:
chmod 777 xcall.sh
xcall.sh jps
即可查看集群里的所有servers的进程
接下来我们可以继续按照以下顺序安装我们想要的组件:
[root@hadoop01 ~]# cd /opt/software/
[root@hadoop01 software]# ls
apache-flume-1.7.0-bin.tar.gz jdk-8u73-linux-x64.tar.gz Python-2.6.6
apache-hive-2.1.0-bin.tar.gz kafka_2.11-0.11.0.2.tgz Python-2.6.6.tar.bz2
apache-storm-1.0.2.tar.gz mysql-5.6.10-linux-glibc2.5-x86_64.tar.gz sqoop-1.4.6.bin__hadoop-2.0.4-alpha.tar.gz
CDH-5.12.1-1.cdh5.12.1.p0.3-el7.parcel mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz user_info.csv
CDH-5.12.1-1.cdh5.12.1.p0.3-el7.parcel.sha1 mysql-connector-java-5.1.31.jar yanagishima-18.0.zip
cloudera-manager-centos7-cm5.12.1_x86_64.tar.gz –p zookeeper-3.4.9.tar.gz
hadoop-2.7.3.tar.gz presto-cli-0.196-executable.jar
hbase-1.2.3-bin.tar.gz presto-server-0.196.tar.gz
安装MySQL(解压mysql压缩包),设置MySQL的root管理员密码
A temporary password is generated for root@localhost: Gspv6.;.TGMI
[root@hadoop01 bin]/usr/local/mysql/support-files/mysql.server start
Starting MySQL… SUCCESS!
将mysql加至服务,以后就可以直接service mysql start,不用usr/local/mysql/support-files/mysql.server start
查看是否service是否已有mysql:
[root@hadoop01 ~]# find /etc/init.d -name mysql
mysql安装在哪里也可以直接用下面这个命令查找:
[root@hadoop01 ~]# find / -name mysql.server
/usr/local/mysql/support-files/mysql.server
将mysql加至服务
[root@hadoop01 ~]# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql
ps -ef|grep mysql 即可看到新启动的mysql
[root@hadoop01 bin]# mysql -uroot -p
Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
[root@hadoop01 bin]# mysql -uroot -h127.0.0.1 -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.24
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
set password for root@localhost = password('123456');
show databases;
Caused by: javax.jdo.JDOFatalDataStoreException: Unable to open a test connection to the given database. JDBC url = jdbc:mysql://hadoop01:3306/hivedb?createDatabaseIfNotExist=true, username = root. Terminating connection pool (set lazyInit to true if you expect to start your database after your app). Original Exception: ------
java.sql.SQLException: null, message from server: "Host 'hadoop01' is not allowed to connect to this MySQL server"
GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' Identified by '123456';
Flush priviledges;
http://hadoop01:50070
(1) HDFS 系统架构
NameNode: 负责响应客户端的请求,维护目录树,管理元数据。(eg: 目录,副本数等)
SecondaryNameNode:加速NameNode启动,负责为NameNode做数据更新,NameNode可能不是最新数据,需要更新。
DataNode: 负责数据存储。文件会按照固定大小(blocksize)切成若干块后分布式存储在若干台DataNode上。每个文件可以有多个副本,存放在不同的DataNode上。
DataNode会定期向NameNode汇报自身所保存的文件block信息,NameNode会负责保持文件的副本Replication数。
客户端请求访问HDFS都是通过向NameNode申请。
NameNode存储目录包含:
edits(编辑日志):记录HDFS所有数据更新操作,编辑日志发生改变后内存中的元数据也会进行更新(越来越大,需要切换,保证单个日志不会特别长)(NameNode是上一个版本的日志的数据,相对滞后)
fsimage(文件系统映像):文件系统元数据的持久性检查点,包含Hadoop中所有文件与目录的inode信息,与编辑日志不同之处在于:不会随着HDFS每次的变化而有所变化。(要与元数据同步,滞后于edits日志。意义在于NameNode关机时,磁盘仍有持久化存储)
checkpoint的触发一般由两种限制,一个是edits logs的大小限制,即fs.checkpoint.size配置;一个是指定时间,即fs.checkpoint.period配置。根据规定,大小的限制是优先的,规定edits文件一旦超过阈值,则不管是否达到最大时间间隔,都会强制checkpoint。
fs.checkpoint.size:规定edits文件最大值,一旦超过这个值(默认64M)将强制执行checkpoint,不管是否已经达到最大时间间隔。
fs.checkpoint.period:指定两次checkpoint的最大时间间隔,默认3600s。
fstime:保存最后一次检查点(checkpoint)信息。
SecondaryNameNode也是edits和fsimage的文件结构。SecondaryNameNode执行过程:从NameNode上下载元数据信息(fsimage、edits),然后把二者合并,生成新的fsimage,在本地保存,并将其推送到NameNode,替换旧的fsimage。
DataNode 相关信息在目录 dfs/data 下:
(2) HDFS写过程
本质上是一个RPC调用,建立pipeline。
(3) HDFS读过程
通过DistributedFileSystem来open一个流对象,将其封装到DFSInputStream对象中。
(4) HDFS基本操作
1、查看根目录下文件列表
hdfs dfs -ls /
2、在hdfs文件系统创建文件夹/test
hdfs dfs -mkdir /test
如果是 root,那应执行:
sudo -u hdfs hadoop fs -mkdir /test
3、上传本地文件filea.txt到hdfs文件系统/test目录中
touch filea.txt
hdfs dfs -put filea.txt /test
4、下载hdfs中/tmp目录到本地/tmp目录
hdfs dfs -get /tmp /tmp/
5、删除hdfs中的/test目录
hdfs dfs -rm -r /test
(5) HDFS运维管理
Hadoop提供了fsck工具对整个文件系统或单独的文件、目录进行健康状态的检查
fsck工具只会列出有问题的文件和block,但是它并不会对它们进行修复
因为我是root用户,所以用了 sudo -u hdfs hdfs fsck /
详细解析参考如下:
(1)在hdfs中创建/test/input目录
hdfs dfs -mkdir -p /test/input
(2)将本地bash.txt文件上传到hdfs的/test/input目录中
hdfs dfs -put bash.txt /test/input
(3)执行wordcount程序
hadoop jar /usr/local/hadoop/share/hadoop/mapreduce/sources/hadoop-mapreduce-examples-2.7.3-sources.jar org.apache.hadoop.examples.WordCount /usr/test/hadoop/input/ /usr/test/hadoop/output
(4)查看运行结果(shell、hdfs Web UI、Yarn Web)
(1) Job提交过程
(2) Yarn任务调度
FIFO Scheduler
Fair Scheduler
Capacity Scheduler
(3) Yarn常用命令
(1) hbase-env.sh
设置JDK_HOME、HADOOP_HOME路径和是否使用HBase自带的Zookeeper(true/false)等。
(2) Hbase-site.xml
hbase.rootdir
hdfs://hadoop01:9000/hbase
hbase.cluster.distributed
true
hbase.zookeeper.quorum
hadoop01:2181,hadoop02:2181,hadoop03:2181
(3) 启动流程:
启动HDFS: start-dfs.sh
启动ZooKeeper:./zkServer.sh start
启动Hbase: ./start-hbase.sh
启动查看: http://hadoop01:16010
1、创建表 user, user 表拥有三个列族分别是 user_id, address, info
hbase shell
hbase(main):003:0> create 'users','user_id','address','info'
hbase(main):004:0> alter 'users','user_id', '{NAME => 'address', VERSIONS => 3}','{NAME => 'info', VERSIONS => 3}'
2、列出所有表
hbase(main):006:0> list
3、查看表 user 属性信息
hbase(main):008:0> desc 'users'
4、向表 user 中插入数据
put 'users','xiaoming','info:age','24'
put 'users','xiaoming','info:birthday','1987-06-17'
put 'users','xiaoming','info:company','alibaba'
put 'users','xiaoming','address:country','china'
put 'users','xiaoming','address:province','zhejiang'
put 'users','xiaoming','address:city','hangzhou'
put 'users','zhangyifei','info:birthday','1987-4-17's
put 'users','zhangyifei','info:favorite','movie'
put 'users','zhangyifei','info:company','alibaba'
put 'users','zhangyifei','address:country','china'
put 'users','zhangyifei','address:province','guangdong'
put 'users','zhangyifei','address:city','jieyang'
put 'users','zhangyifei','address:town','xianqiao'
5、查看表 user 中信息(Web UI)
a、取得一个 id 的所有数据
get 'users','xiaoming'
b、获取一个 id,一个列族的所有数据
get 'users','xiaoming','info'
c、获取一个 id,一个列族中一个列的所有数据
get 'users','xiaoming','info:age'
d、获取整张表数据
6、修改表 user 中信息
a、更新记录
put 'users','xiaoming','info:age' ,'29'
get 'users','xiaoming','info:age'
put 'users','xiaoming','info:age' ,'30'
get 'users','xiaoming','info:age'
b、获取单元格数据的版本数据
get 'users','xiaoming',{COLUMN=>'info:age',VERSIONS=>1} get 'users','xiaoming',{COLUMN=>'info:age',VERSIONS=>2} get 'users','xiaoming',{COLUMN=>'info:age',VERSIONS=>3}
c、获取单元格数据的某个版本数据
get 'users','xiaoming',{COLUMN=>'info:age',TIMESTAMP=>par}
d、统计表的行数
count 'users'
e、扫描全表
scan 'users'
7、删除表 users 中的数据,删除表 users
a、删除 xiaoming 值的'info:age'字段
delete 'users','xiaoming','info:age'
get 'users','xiaoming'
b、删除整行
deleteall 'users','xiaoming'
c、删除表
disable 'users'
drop 'users’
运维
优化
Zookeeper是一个分布式协调服务,为分布式应用程序提供协调8服务,本身是一个分布式程序,只要有半数以上节点存活,zk就能正常服务。服务涵盖:主从协调、服务器节点动态上下线、统一配置管理、分布式共享锁、统一名称服务等,本质上,在底层只提供两个功能:1)管理(存储、读取)用户程序提交的数据;2)并为用户程序提供数据节点监听服务;
Leader是通过内部选举机制临时产生的。
LOOKING:当前Server不知道leader是谁,正在搜寻
LEADING:当前Server即为选举出来的leader
FOLLOWING:Leader已经选举出来,当前Server(Follower)与之同步
(1) hive-site.xml:
(2) 将mysql数据库驱动包 mysql-connector-java-5.1.31.jar 放到 hive lib 目录下,重启数据库
service mysqld restart
(CentOS7或redhat7以上版本,改用systemctl restart mysqld命令重启数据库)
(3) 重新初始化元数据信息
./schematool -dbType –initSchema
1、上传样本数据到vm
2、上传样本数据到hdfs
su – hdfs
hdfs dfs -chmod -r 777 /
hdfs dfs -mkdir /test
hdfs dfs -put *info* /test 3、创建hive表,创建与样本数据对应的三个表,Order_info、Product_info以及 user_info,Hive客户端工具使用Beeline替代旧Hive CLI,具体命令如下所示:
beeline -u jdbc:hive2://localhost:10000 hive cloudera
> create table Product_info (Product_id string, Product_name string, Product_type string,Product_provider string) row format delimited fields terminated by ',' stored as textfile;
> create table Order_info (Order_id string, user_id string, seller_id string, product_id string, number int, time string, deal string) row format delimited fields terminated by ',' stored as textfile;
> create table User_info (user_id string, birthday string, sex string, address string) row format delimited fields terminated by ',' stored as textfile;
4、加载数据到hive表中
> load data inpath '/test/Product_info.csv' overwrite into table product_info;
> load data inpath '/test/Order_info.csv' overwrite into table order_info;
> load data inpath '/test/User_info.csv' overwrite into table user_info;
> select * from product_info;
> select sex,count(*) as count from order_info,user_info where user_info.user_id=order_info.user_id group by sex;
Hive内部表和外部表的区别:
未被external修饰的是内部表(managed table),被external修饰的为外部表(external table)。
区别:
1) 内部表数据由Hive自身管理,外部表数据由HDFS管理;
2) 内部表数据存储的位置是hive.metastore.warehouse.dir(默认:/user/hive/warehouse),外部表数据的存储位置由自己制定(如果没有LOCATION,Hive将在HDFS上的/user/hive/warehouse文件夹下以外部表的表名创建一个文件夹,并将属于这个表的数据存放在这里);
3) 删除内部表会直接删除元数据(metadata)及存储数据;删除外部表仅仅会删除元数据,HDFS上的文件并不会被删除;
1. HiveQL:数据定义
(1)对数据库的操作
创建数据库:
hive的表存放位置模式是由hive-site.xml当中的一个属性指定的 :hive.metastore.warehouse.dir
create database if not exists myhive;
创建数据库并指定hdfs存储位置 :
create database myhive2 location '/myhive2';
修改数据库:
alter database myhive2 set dbproperties('createtime'='20210329');
说明:可以使用alter database 命令来修改数据库的一些属性。但是数据库的元数据信息是不可更改的,包括数据库的名称以及数据库所在的位置
查看数据库详细信息
查看数据库基本信息
hive (myhive)> desc database myhive2;
查看数据库更多详细信息
hive (myhive)> desc database extended myhive2;
删除数据库
删除一个空数据库,如果数据库下面有数据表,那么就会报错
drop database myhive2;
强制删除数据库,包含数据库下面的表一起删除
drop database myhive cascade;
(2)对数据表的操作
a. 对管理表(内部表)的操作
建内部表:
hive (myhive)> use myhive; -- 使用myhive数据库
hive (myhive)> create table stu(id int,name string);
hive (myhive)> insert into stu values (1,"zhangsan");
hive (myhive)> insert into stu values (1,"zhangsan"),(2,"lisi"); -- 一次插入多条数据
hive (myhive)> select * from stu;
hive建表时候的字段类型:
分类 | 类型 | 描述 | 字面量示例 |
---|---|---|---|
原始类型 | BOOLEAN | true/false | TRUE |
TINYINT | 1字节的有符号整数 -128~127 | 1Y | |
SMALLINT | 2个字节的有符号整数,-32768~32767 | 1S | |
INT | 4个字节的带符号整数 | 1 | |
BIGINT | 8字节带符号整数 | 1L | |
FLOAT | 4字节单精度浮点数1.0 | ||
DOUBLE | 8字节双精度浮点数 | 1.0 | |
DEICIMAL | 任意精度的带符号小数 | 1.0 | |
STRING | 字符串,变长 | “a”,’b’ | |
VARCHAR | 变长字符串 | “a”,’b’ | |
CHAR | 固定长度字符串 | “a”,’b’ | |
BINARY | 字节数组 | 无法表示 | |
TIMESTAMP | 时间戳,毫秒值精度 | 122327493795 | |
DATE | 日期 | ‘2016-03-29’ | |
INTERVAL | 时间频率间隔 | ||
复杂类型 | ARRAY | 有序的的同类型的集合 | array(1,2) |
MAP | key-value,key必须为原始类型,value可以任意类型 | map(‘a’,1,’b’,2) | |
STRUCT | 字段集合,类型可以不同 | struct(‘1’,1,1.0), named_struct(‘col1’,’1’,’col2’,1,’clo3’,1.0) | |
UNION | 在有限取值范围内的一个值 | create_union(1,’a’,63) |
对decimal类型简单解释下:
用法:decimal(11,2) 代表最多有11位数字,其中后2位是小数,整数部分是9位;如果整数部分超过9位,则这个字段就会变成null;如果小数部分不足2位,则后面用0补齐两位,如果小数部分超过两位,则超出部分四舍五入
也可直接写 decimal,后面不指定位数,默认是 decimal(10,0) 整数10位,没有小数
创建表并指定字段之间的分隔符
create table if not exists stu2(id int ,name string) row format delimited fields terminated by '\t' stored as textfile location '/user/stu2';
row format delimited fields terminated by '\t' 指定字段分隔符,默认分隔符为 '\001'
stored as 指定存储格式
location 指定存储位置
根据查询结果创建表
create table stu3 as select * from stu2;
根据已经存在的表结构创建表
create table stu4 like stu2;
查询表的结构
只查询表内字段及属性
desc stu2;
详细查询
desc formatted stu2;
查询创建表的语句
show create table stu2;
b. 对外部表操作
外部表因为是指定其他的hdfs路径的数据加载到表当中来,所以hive表会认为自己不完全独占这份数据,所以删除hive表的时候,数据仍然存放在hdfs当中,不会删掉,只会删除表的元数据
构建外部表
create external table student (s_id string,s_name string) row format delimited fields terminated by '\t';
从本地文件系统向表中加载数据
追加操作
load data local inpath '/export/servers/hivedatas/student.csv' into table student;
覆盖操作
load data local inpath '/export/servers/hivedatas/student.csv' overwrite into table student;
从hdfs文件系统向表中加载数据
load data inpath '/hivedatas/teacher.csv' into table teacher;
加载数据到指定分区
load data inpath '/hivedatas/teacher.csv' into table teacher partition(cur_date=20201210);
注意:
1.使用 load data local 表示从本地文件系统加载,文件会拷贝到hdfs上
2.使用 load data 表示从hdfs文件系统加载,文件会直接移动到hive相关目录下,注意不是拷贝过去,因为hive认为hdfs文件已经有3副本了,没必要再次拷贝了
3.如果表是分区表,load 时不指定分区会报错
4.如果加载相同文件名的文件,会被自动重命名
c. 对分区表的操作
创建分区表的语法
create table score(s_id string, s_score int) partitioned by (month string);
创建一个表带多个分区
create table score2 (s_id string, s_score int) partitioned by (year string,month string,day string);
注意:
hive表创建的时候可以用 location 指定一个文件或者文件夹,当指定文件夹时,hive会加载文件夹下的所有文件,当表中无分区时,这个文件夹下不能再有文件夹,否则报错
当表是分区表时,比如 partitioned by (day string), 则这个文件夹下的每一个文件夹就是一个分区,且文件夹名为 day=20201123 这种格式,然后使用:msck repair table score; 修复表结构,成功之后即可看到数据已经全部加载到表当中去了
加载数据到一个分区的表中
load data local inpath '/export/servers/hivedatas/score.csv' into table score partition (month='201806');
加载数据到一个多分区的表中去
load data local inpath '/export/servers/hivedatas/score.csv' into table score2 partition(year='2018',month='06',day='01');
查看分区
show partitions score;
添加一个分区
alter table score add partition(month='201805');
同时添加多个分区
alter table score add partition(month='201804') partition(month = '201803');
注意:添加分区之后就可以在hdfs文件系统当中看到表下面多了一个文件夹
删除分区
alter table score drop partition(month = '201806');
d.对分桶表操作
将数据按照指定的字段进行分成多个桶中去,就是按照分桶字段进行哈希划分到多个文件当中去
分区就是分文件夹,分桶就是分文件
分桶优点:
1. 提高join查询效率
2. 提高抽样效率
开启hive的桶表功能
set hive.enforce.bucketing=true;
设置reduce的个数
set mapreduce.job.reduces=3;
创建桶表
create table course (c_id string,c_name string) clustered by(c_id) into 3 buckets;
桶表的数据加载:由于桶表的数据加载通过hdfs dfs -put文件或者通过load data均不可以,只能通过insert overwrite 进行加载
所以把文件加载到桶表中,需要先创建普通表,并通过insert overwrite的方式将普通表的数据通过查询的方式加载到桶表当中去
通过insert overwrite给桶表中加载数据
insert overwrite table course select * from course_common cluster by(c_id); -- 最后指定桶字段
e. 修改表和删除表
修改表名称
alter table old_table_name rename to new_table_name;
增加/修改列信息
查询表结构
desc score5;
添加列
alter table score5 add columns (mycol string, mysco string);
更新列
alter table score5 change column mysco mysconew int;
删除表操作
drop table score5;
清空表操作
truncate table score6;
说明:只能清空管理表,也就是内部表;清空外部表,会产生错误
注意:truncate 和 drop:
如果 hdfs 开启了回收站,drop 删除的表数据是可以从回收站恢复的,表结构恢复不了,需要自己重新创建;truncate 清空的表是不进回收站的,无法恢复truncate清空的表,
所以 truncate 一定慎用,一旦清空将无力回天
f. 向hive表中加载数据
直接向分区表中插入数据
insert into table score partition(month ='201807') values ('001','002','100');
通过load方式加载数据
load data local inpath '/export/servers/hivedatas/score.csv' overwrite into table score partition(month='201806');
通过查询方式加载数据
insert overwrite table score2 partition(month = '201806') select s_id,c_id,s_score from score1;
查询语句中创建表并加载数据
create table score2 as select * from score1;
在创建表是通过location指定加载数据的路径
create external table score6 (s_id string,c_id string,s_score int) row format delimited fields terminated by ',' location '/myscore';
export 导出与 import 导入 hive表数据(内部表操作)
create table techer2 like techer; --依据已有表结构创建表
export table techer to '/export/techer';
import table techer2 from '/export/techer';
g. hive表中数据导出
insert导出
将查询的结果导出到本地
insert overwrite local directory '/export/servers/exporthive' select * from score;
将查询的结果格式化导出到本地
insert overwrite local directory '/export/servers/exporthive' row format delimited fields terminated by '\t' collection items terminated by '#' select * from student;
将查询的结果导出到HDFS上(没有local)
insert overwrite directory '/export/servers/exporthive' row format delimited fields terminated by '\t' collection items terminated by '#' select * from score;
Hadoop命令导出到本地
dfs -get /export/servers/exporthive/000000_0 /export/servers/exporthive/local.txt;
hive shell 命令导出
基本语法:(hive -f/-e 执行语句或者脚本 > file)
hive -e "select * from myhive.score;" > /export/servers/exporthive/score.txt
hive -f export.sh > /export/servers/exporthive/score.txt
export导出到HDFS上
export table score to '/export/exporthive/score';
2. HiveQL:数据查询
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list [HAVING condition]]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list]
]
[LIMIT number]
注意:
1、order by 会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。
2、sort by不是全局排序,其在数据进入reducer前完成排序。因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只保证每个reducer的输出有序,不保证全局有序。
3、distribute by(字段)根据指定的字段将数据分到不同的reducer,且分发算法是hash散列。
4、Cluster by(字段) 除了具有Distribute by的功能外,还会对该字段进行排序。
因此,如果分桶和sort字段是同一个时,此时,cluster by = distribute by + sort by
WHERE语句
select * from score where s_score < 60;
注意:
小于某个值是不包含null的,如上查询结果是把 s_score 为 null 的行剔除的
GROUP BY 分组
select s_id ,avg(s_score) from score group by s_id;
分组后对数据进行筛选,使用having
select s_id ,avg(s_score) avgscore from score group by s_id having avgscore > 85;
注意:
如果使用 group by 分组,则 select 后面只能写分组的字段或者聚合函数
where和having区别:
1 having是在 group by 分完组之后再对数据进行筛选,所以having 要筛选的字段只能是分组字段或者聚合函数
2 where 是从数据表中的字段直接进行的筛选的,所以不能跟在gruop by后面,也不能使用聚合函数
join 连接
INNER JOIN 内连接:只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来
select * from techer t [inner] join course c on t.t_id = c.t_id; -- inner 可省略
LEFT OUTER JOIN 左外连接:左边所有数据会被返回,右边符合条件的被返回
select * from techer t left join course c on t.t_id = c.t_id; -- outer可省略
RIGHT OUTER JOIN 右外连接:右边所有数据会被返回,左边符合条件的被返回、
select * from techer t right join course c on t.t_id = c.t_id;
FULL OUTER JOIN 满外(全外)连接: 将会返回所有表中符合条件的所有记录。如果任一表的指定字段没有符合条件的值的话,那么就使用NULL值替代。
SELECT * FROM techer t FULL JOIN course c ON t.t_id = c.t_id ;
注:1. hive2版本已经支持不等值连接,就是 join on条件后面可以使用大于小于符号了;并且也支持 join on 条件后跟or (早前版本 on 后只支持 = 和 and,不支持 > < 和 or)
2.如hive执行引擎使用MapReduce,一个join就会启动一个job,一条sql语句中如有多个join,则会启动多个job
注意:表之间用逗号(,)连接和 inner join 是一样的
select * from table_a,table_b where table_a.id=table_b.id;
它们的执行效率没有区别,只是书写方式不同,用逗号是sql 89标准,join 是sql 92标准。用逗号连接后面过滤条件用 where ,用 join 连接后面过滤条件是 on。
order by 排序
全局排序,只会有一个reduce
ASC(ascend): 升序(默认) DESC(descend): 降序
SELECT * FROM student s LEFT JOIN score sco ON s.s_id = sco.s_id ORDER BY sco.s_score DESC;
注意:order by 是全局排序,所以最后只有一个reduce,也就是在一个节点执行,如果数据量太大,就会耗费较长时间
sort by 局部排序
每个MapReduce内部进行排序,对全局结果集来说不是排序。
设置reduce个数
set mapreduce.job.reduces=3;
查看设置reduce个数
set mapreduce.job.reduces;
查询成绩按照成绩降序排列
select * from score sort by s_score;
将查询结果导入到文件中(按照成绩降序排列)
insert overwrite local directory '/export/servers/hivedatas/sort' select * from score sort by s_score;
distribute by 分区排序
distribute by:类似MR中partition,进行分区,结合sort by使用
设置reduce的个数,将我们对应的s_id划分到对应的reduce当中去
set mapreduce.job.reduces=7;
通过distribute by 进行数据的分区
select * from score distribute by s_id sort by s_score;
注意:Hive要求 distribute by 语句要写在 sort by 语句之前
cluster by
当distribute by和sort by字段相同时,可以使用cluster by方式.
cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是正序排序,不能指定排序规则为ASC或者DESC。
以下两种写法等价
select * from score cluster by s_id;
select * from score distribute by s_id sort by s_id;
Hive函数
聚合函数
hive支持 count(),max(),min(),sum(),avg() 等常用的聚合函数
注意:
聚合操作时要注意null值
count(*) 包含null值,统计所有行数
count(id) 不包含null值
min 求最小值是不包含null,除非所有值都是null
avg 求平均值也是不包含null
非空集合总体变量函数: var_pop
语法: var_pop(col)
返回值: double
说明: 统计结果集中col非空集合的总体变量(忽略null)
非空集合样本变量函数: var_samp
语法: var_samp (col)
返回值: double
说明: 统计结果集中col非空集合的样本变量(忽略null)
总体标准偏离函数: stddev_pop
语法: stddev_pop(col)
返回值: double
说明: 该函数计算总体标准偏离,并返回总体变量的平方根,其返回值与VAR_POP函数的平方根相同
中位数函数: percentile
语法: percentile(BIGINT col, p)
返回值: double
说明: 求准确的第pth个百分位数,p必须介于0和1之间,但是col字段目前只支持整数,不支持浮点数类型
关系运算
支持:等值(=)、不等值(!= 或 <>)、小于(<)、小于等于(<=)、大于(>)、大于等于(>=)
空值判断(is null)、非空判断(is not null)
LIKE比较: LIKE
语法: A LIKE B
操作类型: strings
描述: 如果字符串A或者字符串B为NULL,则返回NULL;如果字符串A符合表达式B 的正则语法,则为TRUE;否则为FALSE。B中字符”_”表示任意单个字符,而字符”%”表示任意数量的字符。
JAVA的LIKE操作: RLIKE
语法: A RLIKE B
操作类型: strings
描述: 如果字符串A或者字符串B为NULL,则返回NULL;如果字符串A符合JAVA正则表达式B的正则语法,则为TRUE;否则为FALSE。
REGEXP操作: REGEXP
语法: A REGEXP B
操作类型: strings
描述: 功能与RLIKE相同
示例:select 1 from tableName where 'footbar' REGEXP '^f.*r$';
结果:1
数学运算
支持所有数值类型:加(+)、减(-)、乘(*)、除(/)、取余(%)、位与(&)、位或(|)、位异或(^)、位取反(~)
逻辑运算
支持:逻辑与(and)、逻辑或(or)、逻辑非(not)
数值运算
取整函数: round
语法: round(double a)
返回值: BIGINT
说明: 返回double类型的整数值部分 (遵循四舍五入)
示例:select round(3.1415926) from tableName;
结果:3
指定精度取整函数: round
语法: round(double a, int d)
返回值: DOUBLE
说明: 返回指定精度d的double类型
hive> select round(3.1415926,4) from tableName;
3.1416
向下取整函数: floor
语法: floor(double a)
返回值: BIGINT
说明: 返回等于或者小于该double变量的最大的整数
hive> select floor(3.641) from tableName;
3
向上取整函数: ceil
语法: ceil(double a)
返回值: BIGINT
说明: 返回等于或者大于该double变量的最小的整数
hive> select ceil(3.1415926) from tableName;
4
取随机数函数: rand
语法: rand(),rand(int seed)
返回值: double
说明: 返回一个0到1范围内的随机数。如果指定种子seed,则会等到一个稳定的随机数序列
hive> select rand() from tableName; -- 每次执行此语句得到的结果都不同
0.5577432776034763
hive> select rand(100) ; -- 只要指定种子,每次执行此语句得到的结果一样的
0.7220096548596434
自然指数函数: exp
语法: exp(double a)
返回值: double
说明: 返回自然对数e的a次方
hive> select exp(2) ;
7.38905609893065
以10为底对数函数: log10
语法: log10(double a)
返回值: double
说明: 返回以10为底的a的对数
hive> select log10(100) ;
2.0
此外还有:以2为底对数函数: log2()、对数函数: log()
幂运算函数: pow
语法: pow(double a, double p)
返回值: double
说明: 返回a的p次幂
hive> select pow(2,4) ;
16.0
开平方函数: sqrt
语法: sqrt(double a)
返回值: double
说明: 返回a的平方根
hive> select sqrt(16) ;
4.0
二进制函数: bin
语法: bin(BIGINT a)
返回值: string
说明: 返回a的二进制代码表示
hive> select bin(7) ;
111
十六进制函数: hex()、将十六进制转化为字符串函数: unhex()
进制转换函数: conv(bigint num, int from_base, int to_base) 说明: 将数值num从from_base进制转化到to_base进制
此外还有很多数学函数:绝对值函数: abs()、正取余函数: pmod()、正弦函数: sin()、反正弦函数: asin()、余弦函数: cos()、反余弦函数: acos()、positive函数: positive()、negative函数: negative()
条件函数
If函数: if
语法: if(boolean testCondition, T valueTrue, T valueFalseOrNull)
返回值: T
说明: 当条件testCondition为TRUE时,返回valueTrue;否则返回valueFalseOrNull
hive> select if(1=2,100,200) ;
200
hive> select if(1=1,100,200) ;
100
非空查找函数: coalesce
语法: coalesce(T v1, T v2, …)
返回值: T
说明: 返回参数中的第一个非空值;如果所有值都为NULL,那么返回NULL
hive> select coalesce(null,'100','50') ;
100
条件判断函数:case when (两种写法,其一)
语法: case when a then b [when c then d]* [else e] end
返回值: T
说明:如果a为TRUE,则返回b;如果c为TRUE,则返回d;否则返回e
hive> select case when 1=2 then 'tom' when 2=2 then 'mary' else 'tim' end from tableName;
mary
条件判断函数:case when (两种写法,其二)
语法: case a when b then c [when d then e]* [else f] end
返回值: T
说明:如果a等于b,那么返回c;如果a等于d,那么返回e;否则返回f
hive> Select case 100 when 50 then 'tom' when 100 then 'mary' else 'tim' end from tableName;
mary
日期函数
注:以下SQL语句中的 from tableName 可去掉,不影响查询结果
获取当前UNIX时间戳函数: unix_timestamp
语法: unix_timestamp()
返回值: bigint
说明: 获得当前时区的UNIX时间戳
hive> select unix_timestamp() from tableName;
1616906976
UNIX时间戳转日期函数: from_unixtime
语法: from_unixtime(bigint unixtime[, string format])
返回值: string
说明: 转化UNIX时间戳(从1970-01-01 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式
hive> select from_unixtime(1616906976,'yyyyMMdd') from tableName;
20210328
日期转UNIX时间戳函数: unix_timestamp
语法: unix_timestamp(string date)
返回值: bigint
说明: 转换格式为"yyyy-MM-dd HH:mm:ss"的日期到UNIX时间戳。如果转化失败,则返回0。
hive> select unix_timestamp('2021-03-08 14:21:15') from tableName;
1615184475
指定格式日期转UNIX时间戳函数: unix_timestamp
语法: unix_timestamp(string date, string pattern)
返回值: bigint
说明: 转换pattern格式的日期到UNIX时间戳。如果转化失败,则返回0。
hive> select unix_timestamp('2021-03-08 14:21:15','yyyyMMdd HH:mm:ss') from tableName;
1615184475
日期时间转日期函数: to_date
语法: to_date(string timestamp)
返回值: string
说明: 返回日期时间字段中的日期部分。
hive> select to_date('2021-03-28 14:03:01') from tableName;
2021-03-28
日期转年函数: year
语法: year(string date)
返回值: int
说明: 返回日期中的年。
hive> select year('2021-03-28 10:03:01') from tableName;
2021
hive> select year('2021-03-28') from tableName;
2021
日期转月函数: month
语法: month (string date)
返回值: int
说明: 返回日期中的月份。
hive> select month('2020-12-28 12:03:01') from tableName;
12
hive> select month('2021-03-08') from tableName;
8
日期转天函数: day
语法: day (string date)
返回值: int
说明: 返回日期中的天。
hive> select day('2020-12-08 10:03:01') from tableName;
8
hive> select day('2020-12-24') from tableName;
24
日期转小时函数: hour
语法: hour (string date)
返回值: int
说明: 返回日期中的小时。
hive> select hour('2020-12-08 10:03:01') from tableName;
10
日期转分钟函数: minute
语法: minute (string date)
返回值: int
说明: 返回日期中的分钟。
hive> select minute('2020-12-08 10:03:01') from tableName;
3
日期转秒函数: second
语法: second (string date)
返回值: int
说明: 返回日期中的秒。
hive> select second('2020-12-08 10:03:01') from tableName;
1
日期转周函数: weekofyear
语法: weekofyear (string date)
返回值: int
说明: 返回日期在当前的周数。
hive> select weekofyear('2020-12-08 10:03:01') from tableName;
49
日期比较函数: datediff
语法: datediff(string enddate, string startdate)
返回值: int
说明: 返回结束日期减去开始日期的天数。
hive> select datediff('2020-12-08','2012-05-09') from tableName;
213
日期增加函数: date_add
语法: date_add(string startdate, int days)
返回值: string
说明: 返回开始日期startdate增加days天后的日期。
hive> select date_add('2020-12-08',10) from tableName;
2020-12-18
日期减少函数: date_sub
语法: date_sub (string startdate, int days)
返回值: string
说明: 返回开始日期startdate减少days天后的日期。
hive> select date_sub('2020-12-08',10) from tableName;
2020-11-28
字符串函数
字符串长度函数:length
语法: length(string A)
返回值: int
说明:返回字符串A的长度
hive> select length('abcedfg') from tableName;
7
字符串反转函数:reverse
语法: reverse(string A)
返回值: string
说明:返回字符串A的反转结果
hive> select reverse('abcedfg') from tableName;
gfdecba
字符串连接函数:concat
语法: concat(string A, string B…)
返回值: string
说明:返回输入字符串连接后的结果,支持任意个输入字符串
hive> select concat('abc','def’,'gh')from tableName;
abcdefgh
带分隔符字符串连接函数:concat_ws
语法: concat_ws(string SEP, string A, string B…)
返回值: string
说明:返回输入字符串连接后的结果,SEP表示各个字符串间的分隔符
hive> select concat_ws(',','abc','def','gh')from tableName;
abc,def,gh
字符串截取函数:substr,substring
语法: substr(string A, int start),substring(string A, int start)
返回值: string
说明:返回字符串A从start位置到结尾的字符串
hive> select substr('abcde',3) from tableName;
cde
hive> select substring('abcde',3) from tableName;
cde
hive> select substr('abcde',-1) from tableName; (和ORACLE相同)
e
字符串截取函数:substr,substring
语法: substr(string A, int start, int len),substring(string A, int start, int len)
返回值: string
说明:返回字符串A从start位置开始,长度为len的字符串
hive> select substr('abcde',3,2) from tableName;
cd
hive> select substring('abcde',3,2) from tableName;
cd
hive>select substring('abcde',-2,2) from tableName;
de
字符串转大写函数:upper,ucase
语法: upper(string A) ucase(string A)
返回值: string
说明:返回字符串A的大写格式
hive> select upper('abSEd') from tableName;
ABSED
hive> select ucase('abSEd') from tableName;
ABSED
字符串转小写函数:lower,lcase
语法: lower(string A) lcase(string A)
返回值: string
说明:返回字符串A的小写格式
hive> select lower('abSEd') from tableName;
absed
hive> select lcase('abSEd') from tableName;
absed
去空格函数:trim
语法: trim(string A)
返回值: string
说明:去除字符串两边的空格
hive> select trim(' abc ') from tableName;
abc
左边去空格函数:ltrim
语法: ltrim(string A)
返回值: string
说明:去除字符串左边的空格
hive> select ltrim(' abc ') from tableName;
abc
右边去空格函数:rtrim
语法: rtrim(string A)
返回值: string
说明:去除字符串右边的空格
hive> select rtrim(' abc ') from tableName;
abc
正则表达式替换函数:regexp_replace
语法: regexp_replace(string A, string B, string C)
返回值: string
说明:将字符串A中的符合java正则表达式B的部分替换为C。注意,在有些情况下要使用转义字符,类似oracle中的regexp_replace函数。
hive> select regexp_replace('foobar', 'oo|ar', '') from tableName;
fb
正则表达式解析函数:regexp_extract
语法: regexp_extract(string subject, string pattern, int index)
返回值: string
说明:将字符串subject按照pattern正则表达式的规则拆分,返回index指定的字符。
hive> select regexp_extract('foothebar', 'foo(.*?)(bar)', 1) from tableName;
the
hive> select regexp_extract('foothebar', 'foo(.*?)(bar)', 2) from tableName;
bar
hive> select regexp_extract('foothebar', 'foo(.*?)(bar)', 0) from tableName;
foothebar
strong>注意,在有些情况下要使用转义字符,下面的等号要用双竖线转义,这是java正则表达式的规则。
select data_field,
regexp_extract(data_field,'.*?bgStart\\=([^&]+)',1) as aaa,
regexp_extract(data_field,'.*?contentLoaded_headStart\\=([^&]+)',1) as bbb,
regexp_extract(data_field,'.*?AppLoad2Req\\=([^&]+)',1) as ccc
from pt_nginx_loginlog_st
where pt = '2021-03-28' limit 2;
URL解析函数:parse_url
语法: parse_url(string urlString, string partToExtract [, string keyToExtract])
返回值: string
说明:返回URL中指定的部分。partToExtract的有效值为:HOST, PATH, QUERY, REF, PROTOCOL, AUTHORITY, FILE, and USERINFO.
hive> select parse_url
('https://www.tableName.com/path1/p.php?k1=v1&k2=v2#Ref1', 'HOST')
from tableName;
www.tableName.com
hive> select parse_url
('https://www.tableName.com/path1/p.php?k1=v1&k2=v2#Ref1', 'QUERY', 'k1')
from tableName;
v1
json解析函数:get_json_object
语法: get_json_object(string json_string, string path)
返回值: string
说明:解析json的字符串json_string,返回path指定的内容。如果输入的json字符串无效,那么返回NULL。
hive> select get_json_object('{"store":{"fruit":\[{"weight":8,"type":"apple"},{"weight":9,"type":"pear"}], "bicycle":{"price":19.95,"color":"red"} },"email":"amy@only_for_json_udf_test.net","owner":"amy"}','$.owner') from tableName;
空格字符串函数:space
语法: space(int n)
返回值: string
说明:返回长度为n的字符串
hive> select space(10) from tableName;
hive> select length(space(10)) from tableName;
10
重复字符串函数:repeat
语法: repeat(string str, int n)
返回值: string
说明:返回重复n次后的str字符串
hive> select repeat('abc',5) from tableName;
abcabcabcabcabc
首字符ascii函数:ascii
语法: ascii(string str)
返回值: int
说明:返回字符串str第一个字符的ascii码
hive> select ascii('abcde') from tableName;
97
左补足函数:lpad
语法: lpad(string str, int len, string pad)
返回值: string
说明:将str进行用pad进行左补足到len位
hive> select lpad('abc',10,'td') from tableName;
tdtdtdtabc
注意:与GP,ORACLE不同,pad 不能默认
右补足函数:rpad
语法: rpad(string str, int len, string pad)
返回值: string
说明:将str进行用pad进行右补足到len位
hive> select rpad('abc',10,'td') from tableName;
abctdtdtdt
分割字符串函数: split
语法: split(string str, string pat)
返回值: array
说明: 按照pat字符串分割str,会返回分割后的字符串数组
hive> select split('abtcdtef','t') from tableName;
["ab","cd","ef"]
集合查找函数: find_in_set
语法: find_in_set(string str, string strList)
返回值: int
说明: 返回str在strlist第一次出现的位置,strlist是用逗号分割的字符串。如果没有找该str字符,则返回0
hive> select find_in_set('ab','ef,ab,de') from tableName;
2
hive> select find_in_set('at','ef,ab,de') from tableName;
0
复合类型构建操作
Map类型构建: map
语法: map (key1, value1, key2, value2, …)
说明:根据输入的key和value对构建map类型
hive> Create table mapTable as select map('100','tom','200','mary') as t from tableName;
hive> describe mapTable;
t map
hive> select t from tableName;
{"100":"tom","200":"mary"}
Struct类型构建: struct
语法: struct(val1, val2, val3, …)
说明:根据输入的参数构建结构体struct类型
hive> create table struct_table as select struct('tom','mary','tim') as t from tableName;
hive> describe struct_table;
t struct
hive> select t from tableName;
{"col1":"tom","col2":"mary","col3":"tim"}
array类型构建: array
语法: array(val1, val2, …)
说明:根据输入的参数构建数组array类型
hive> create table arr_table as select array("tom","mary","tim") as t from tableName;
hive> describe tableName;
t array
hive> select t from tableName;
["tom","mary","tim"]
复杂类型访问操作
array类型访问: A[n]
语法: A[n]
操作类型: A为array类型,n为int类型
说明:返回数组A中的第n个变量值。数组的起始下标为0。比如,A是个值为['foo', 'bar']的数组类型,那么A[0]将返回'foo',而A[1]将返回'bar'
hive> create table arr_table2 as select array("tom","mary","tim") as t
from tableName;
hive> select t[0],t[1] from arr_table2;
tom mary tim
map类型访问: M[key]
语法: M[key]
操作类型: M为map类型,key为map中的key值
说明:返回map类型M中,key值为指定值的value值。比如,M是值为{'f' -> 'foo', 'b' -> 'bar', 'all' -> 'foobar'}的map类型,那么M['all']将会返回'foobar'
hive> Create table map_table2 as select map('100','tom','200','mary') as t from tableName;
hive> select t['200'],t['100'] from map_table2;
mary tom
struct类型访问: S.x
语法: S.x
操作类型: S为struct类型
说明:返回结构体S中的x字段。比如,对于结构体struct foobar {int foo, int bar},foobar.foo返回结构体中的foo字段
hive> create table str_table2 as select struct('tom','mary','tim') as t from tableName;
hive> describe tableName;
t struct
hive> select t.col1,t.col3 from str_table2;
tom tim
复杂类型长度统计函数
Map类型长度函数: size(Map
语法: size(Map)
返回值: int
说明: 返回map类型的长度
hive> select size(t) from map_table2;
2
array类型长度函数: size(Array)
语法: size(Array)
返回值: int
说明: 返回array类型的长度
hive> select size(t) from arr_table2;
4
类型转换函数 ***
类型转换函数: cast
语法: cast(expr as )
返回值: Expected "=" to follow "type"
说明: 返回转换后的数据类型
hive> select cast('1' as bigint) from tableName;
1
hive当中的lateral view 与 explode以及reflect和窗口函数
使用explode函数将hive表中的Map和Array字段数据进行拆分
lateral view用于和split、explode等UDTF一起使用的,能将一行数据拆分成多行数据,在此基础上可以对拆分的数据进行聚合,lateral view首先为原始表的每行调用UDTF,UDTF会把一行拆分成一行或者多行,lateral view在把结果组合,产生一个支持别名表的虚拟表。
其中explode还可以用于将hive一列中复杂的array或者map结构拆分成多行
需求:现在有数据格式如下
zhangsan child1,child2,child3,child4 k1:v1,k2:v2
lisi child5,child6,child7,child8 k3:v3,k4:v4
字段之间使用\t分割,需求将所有的child进行拆开成为一列
+----------+--+
| mychild |
+----------+--+
| child1 |
| child2 |
| child3 |
| child4 |
| child5 |
| child6 |
| child7 |
| child8 |
+----------+--+
将map的key和value也进行拆开,成为如下结果
+-----------+-------------+--+
| mymapkey | mymapvalue |
+-----------+-------------+--+
| k1 | v1 |
| k2 | v2 |
| k3 | v3 |
| k4 | v4 |
+-----------+-------------+--+
创建hive数据库
创建hive数据库
hive (default)> create database hive_explode;
hive (default)> use hive_explode;
创建hive表,然后使用explode拆分map和array
hive (hive_explode)> create table t3(name string,children array,address Map) row format delimited fields terminated by '\t' collection items terminated by ',' map keys terminated by ':' stored as textFile;
加载数据
node03执行以下命令创建表数据文件
mkdir -p /export/servers/hivedatas/
cd /export/servers/hivedatas/
vim maparray
内容如下:
zhangsan child1,child2,child3,child4 k1:v1,k2:v2
lisi child5,child6,child7,child8 k3:v3,k4:v4
hive表当中加载数据
hive (hive_explode)> load data local inpath '/export/servers/hivedatas/maparray' into table t3;
使用explode将hive当中数据拆开
将array当中的数据拆分开
hive (hive_explode)> SELECT explode(children) AS myChild FROM t3;
将map当中的数据拆分开
hive (hive_explode)> SELECT explode(address) AS (myMapKey, myMapValue) FROM t3;
使用explode拆分json字符串
需求: 需求:现在有一些数据格式如下:
a:shandong,b:beijing,c:hebei|1,2,3,4,5,6,7,8,9|[{"source":"7fresh","monthSales":4900,"userCount":1900,"score":"9.9"},{"source":"jd","monthSales":2090,"userCount":78981,"score":"9.8"},{"source":"jdmart","monthSales":6987,"userCount":1600,"score":"9.0"}]
其中字段与字段之间的分隔符是 |
我们要解析得到所有的monthSales对应的值为以下这一列(行转列)
4900
2090
6987
创建hive表
hive (hive_explode)> create table explode_lateral_view
> (`area` string,
> `goods_id` string,
> `sale_info` string)
> ROW FORMAT DELIMITED
> FIELDS TERMINATED BY '|'
> STORED AS textfile;
准备数据并加载数据
准备数据如下
cd /export/servers/hivedatas
vim explode_json
a:shandong,b:beijing,c:hebei|1,2,3,4,5,6,7,8,9|[{"source":"7fresh","monthSales":4900,"userCount":1900,"score":"9.9"},{"source":"jd","monthSales":2090,"userCount":78981,"score":"9.8"},{"source":"jdmart","monthSales":6987,"userCount":1600,"score":"9.0"}]
加载数据到hive表当中去
hive (hive_explode)> load data local inpath '/export/servers/hivedatas/explode_json' overwrite into table explode_lateral_view;
使用explode拆分Array
hive (hive_explode)> select explode(split(goods_id,',')) as goods_id from explode_lateral_view;
使用explode拆解Map
hive (hive_explode)> select explode(split(area,',')) as area from explode_lateral_view;
拆解json字段
hive (hive_explode)> select explode(split(regexp_replace(regexp_replace(sale_info,'\\[\\{',''),'}]',''),'},\\{')) as sale_info from explode_lateral_view;
然后我们想用get_json_object来获取key为monthSales的数据:
hive (hive_explode)> select get_json_object(explode(split(regexp_replace(regexp_replace(sale_info,'\\[\\{',''),'}]',''),'},\\{')),'$.monthSales') as sale_info from explode_lateral_view;
然后挂了FAILED: SemanticException [Error 10081]: UDTF's are not supported outside the SELECT clause, nor nested in expressions
UDTF explode不能写在别的函数内
如果你这么写,想查两个字段,select explode(split(area,',')) as area,good_id from explode_lateral_view;
会报错FAILED: SemanticException 1:40 Only a single expression in the SELECT clause is supported with UDTF's. Error encountered near token 'good_id'
使用UDTF的时候,只支持一个字段,这时候就需要LATERAL VIEW出场了
配合LATERAL VIEW使用
配合lateral view查询多个字段
hive (hive_explode)> select goods_id2,sale_info from explode_lateral_view LATERAL VIEW explode(split(goods_id,','))goods as goods_id2;
其中LATERAL VIEW explode(split(goods_id,','))goods相当于一个虚拟表,与原表explode_lateral_view笛卡尔积关联
也可以多重使用
hive (hive_explode)> select goods_id2,sale_info,area2
from explode_lateral_view
LATERAL VIEW explode(split(goods_id,','))goods as goods_id2
LATERAL VIEW explode(split(area,','))area as area2;也是三个表笛卡尔积的结果
最终,我们可以通过下面的句子,把这个json格式的一行数据,完全转换成二维表的方式展现
hive (hive_explode)> select get_json_object(concat('{',sale_info_1,'}'),'$.source') as source,get_json_object(concat('{',sale_info_1,'}'),'$.monthSales') as monthSales,get_json_object(concat('{',sale_info_1,'}'),'$.userCount') as monthSales,get_json_object(concat('{',sale_info_1,'}'),'$.score') as monthSales from explode_lateral_view LATERAL VIEW explode(split(regexp_replace(regexp_replace(sale_info,'\\[\\{',''),'}]',''),'},\\{'))sale_info as sale_info_1;
总结:
Lateral View通常和UDTF一起出现,为了解决UDTF不允许在select字段的问题。Multiple Lateral View可以实现类似笛卡尔乘积。Outer关键字可以把不输出的UDTF的空结果,输出成NULL,防止丢失数据。
行转列
相关参数说明:
CONCAT(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意个输入字符串;
CONCAT_WS(separator, str1, str2,...):它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;
COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。
数据准备:
name |
constellation |
blood_type |
---|---|---|
孙悟空 |
白羊座 |
A |
老王 |
射手座 |
A |
宋宋 |
白羊座 |
B |
猪八戒 |
白羊座 |
A |
凤姐 |
射手座 |
A |
需求: 把星座和血型一样的人归类到一起。结果如下:
射手座,A 老王|凤姐
白羊座,A 孙悟空|猪八戒
白羊座,B 宋宋
实现步骤:
创建本地constellation.txt,导入数据
node03服务器执行以下命令创建文件,注意数据使用\t进行分割
cd /export/servers/hivedatas
vim constellation.txt
数据如下:
孙悟空 白羊座 A
老王 射手座 A
宋宋 白羊座 B
猪八戒 白羊座 A
凤姐 射手座 A
创建hive表并导入数据
创建hive表并加载数据
hive (hive_explode)> create table person_info(
name string,
constellation string,
blood_type string)
row format delimited fields terminated by "\t";
加载数据
hive (hive_explode)> load data local inpath '/export/servers/hivedatas/constellation.txt' into table person_info;
按需求查询数据
hive (hive_explode)> select
t1.base,
concat_ws('|', collect_set(t1.name)) name
from
(select
name,
concat(constellation, "," , blood_type) base
from
person_info) t1
group by
t1.base;
列转行
所需函数:
EXPLODE(col):将hive一列中复杂的array或者map结构拆分成多行。
LATERAL VIEW
用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias
解释:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。
数据准备:
cd /export/servers/hivedatas
vim movie.txt
文件内容如下: 数据字段之间使用\t进行分割
《疑犯追踪》 悬疑,动作,科幻,剧情
《Lie to me》 悬疑,警匪,动作,心理,剧情
《战狼2》 战争,动作,灾难
需求: 将电影分类中的数组数据展开。结果如下:
《疑犯追踪》 悬疑
《疑犯追踪》 动作
《疑犯追踪》 科幻
《疑犯追踪》 剧情
《Lie to me》 悬疑
《Lie to me》 警匪
《Lie to me》 动作
《Lie to me》 心理
《Lie to me》 剧情
《战狼2》 战争
《战狼2》 动作
《战狼2》 灾难
实现步骤:
创建hive表
create table movie_info(
movie string,
category array)
row format delimited fields terminated by "\t"
collection items terminated by ",";
加载数据
load data local inpath "/export/servers/hivedatas/movie.txt" into table movie_info;
按需求查询数据
select
movie,
category_name
from
movie_info lateral view explode(category) table_tmp as category_name;
reflect函数
reflect函数可以支持在sql中调用java中的自带函数,秒杀一切udf函数。
需求1: 使用java.lang.Math当中的Max求两列中最大值
实现步骤:
创建hive表
create table test_udf(col1 int,col2 int) row format delimited fields terminated by ',';
准备数据并加载数据
cd /export/servers/hivedatas
vim test_udf
文件内容如下:
1,2
4,3
6,4
7,5
5,6
加载数据
hive (hive_explode)> load data local inpath '/export/servers/hivedatas/test_udf' overwrite into table test_udf;
使用java.lang.Math当中的Max求两列当中的最大值
hive (hive_explode)> select reflect("java.lang.Math","max",col1,col2) from test_udf;
需求2: 文件中不同的记录来执行不同的java的内置函数
实现步骤:
创建hive表
hive (hive_explode)> create table test_udf2(class_name string,method_name string,col1 int , col2 int) row format delimited fields terminated by ',';
准备数据
cd /export/servers/hivedatas
vim test_udf2
文件内容如下:
java.lang.Math,min,1,2
java.lang.Math,max,2,3
加载数据
hive (hive_explode)> load data local inpath '/export/servers/hivedatas/test_udf2' overwrite into table test_udf2;
执行查询
hive (hive_explode)> select reflect(class_name,method_name,col1,col2) from test_udf2;
需求3: 判断是否为数字
实现方式:
使用apache commons中的函数,commons下的jar已经包含在hadoop的classpath中,所以可以直接使用。
select reflect("org.apache.commons.lang.math.NumberUtils","isNumber","123")
窗口函数与分析函数
在sql中有一类函数叫做聚合函数,例如sum()、avg()、max()等等,这类函数可以将多行数据按照规则聚集为一行,一般来讲聚集后的行数是要少于聚集前的行数的。但是有时我们想要既显示聚集前的数据,又要显示聚集后的数据,这时我们便引入了窗口函数。窗口函数又叫OLAP函数/分析函数,窗口函数兼具分组和排序功能。
窗口函数最重要的关键字是 partition by 和 order by。
具体语法如下:over (partition by xxx order by xxx)
sum、avg、min、max
准备数据
建表语句:
create table test_t1(
cookieid string,
createtime string, --day
pv int
) row format delimited
fields terminated by ',';
加载数据:
load data local inpath '/root/hivedata/test_t1.dat' into table test_t1;
cookie1,2020-04-10,1
cookie1,2020-04-11,5
cookie1,2020-04-12,7
cookie1,2020-04-13,3
cookie1,2020-04-14,2
cookie1,2020-04-15,4
cookie1,2020-04-16,4
开启智能本地模式
SET hive.exec.mode.local.auto=true;
SUM函数和窗口函数的配合使用:结果和ORDER BY相关,默认为升序。
select cookieid,createtime,pv,
sum(pv) over(partition by cookieid order by createtime) as pv1
from test_t1;
select cookieid,createtime,pv,
sum(pv) over(partition by cookieid order by createtime rows between unbounded preceding and current row) as pv2
from test_t1;
select cookieid,createtime,pv,
sum(pv) over(partition by cookieid) as pv3
from test_t1;
select cookieid,createtime,pv,
sum(pv) over(partition by cookieid order by createtime rows between 3 preceding and current row) as pv4
from test_t1;
select cookieid,createtime,pv,
sum(pv) over(partition by cookieid order by createtime rows between 3 preceding and 1 following) as pv5
from test_t1;
select cookieid,createtime,pv,
sum(pv) over(partition by cookieid order by createtime rows between current row and unbounded following) as pv6
from test_t1;
pv1: 分组内从起点到当前行的pv累积,如,11号的pv1=10号的pv+11号的pv, 12号=10号+11号+12号
pv2: 同pv1
pv3: 分组内(cookie1)所有的pv累加
pv4: 分组内当前行+往前3行,如,11号=10号+11号, 12号=10号+11号+12号,
13号=10号+11号+12号+13号, 14号=11号+12号+13号+14号
pv5: 分组内当前行+往前3行+往后1行,如,14号=11号+12号+13号+14号+15号=5+7+3+2+4=21
pv6: 分组内当前行+往后所有行,如,13号=13号+14号+15号+16号=3+2+4+4=13,
14号=14号+15号+16号=2+4+4=10
如果不指定rows between,默认为从起点到当前行;
如果不指定order by,则将分组内所有值累加;
关键是理解rows between含义,也叫做window子句:
preceding:往前
following:往后
current row:当前行
unbounded:起点
unbounded preceding 表示从前面的起点
unbounded following:表示到后面的终点
AVG,MIN,MAX,和SUM用法一样。
row_number、rank、dense_rank、ntile
准备数据
cookie1,2020-04-10,1
cookie1,2020-04-11,5
cookie1,2020-04-12,7
cookie1,2020-04-13,3
cookie1,2020-04-14,2
cookie1,2020-04-15,4
cookie1,2020-04-16,4
cookie2,2020-04-10,2
cookie2,2020-04-11,3
cookie2,2020-04-12,5
cookie2,2020-04-13,6
cookie2,2020-04-14,3
cookie2,2020-04-15,9
cookie2,2020-04-16,7
CREATE TABLE test_t2 (
cookieid string,
createtime string, --day
pv INT
) ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
stored as textfile;
加载数据:
load data local inpath '/root/hivedata/test_t2.dat' into table test_t2;
ROW_NUMBER()使用
ROW_NUMBER()从1开始,按照顺序,生成分组内记录的序列。
SELECT
cookieid,
createtime,
pv,
ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn
FROM test_t2;
RANK 和 DENSE_RANK使用
RANK() 生成数据项在分组中的排名,排名相等会在名次中留下空位 。
DENSE_RANK()生成数据项在分组中的排名,排名相等会在名次中不会留下空位。
SELECT
cookieid,
createtime,
pv,
RANK() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn1,
DENSE_RANK() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn2,
ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY pv DESC) AS rn3
FROM test_t2
WHERE cookieid = 'cookie1';
NTILE
有时会有这样的需求:如果数据排序后分为三部分,业务人员只关心其中的一部分,如何将这中间的三分之一数据拿出来呢?NTILE函数即可以满足。
ntile可以看成是:把有序的数据集合平均分配到指定的数量(num)个桶中, 将桶号分配给每一行。如果不能平均分配,则优先分配较小编号的桶,并且各个桶中能放的行数最多相差1。
然后可以根据桶号,选取前或后 n分之几的数据。数据会完整展示出来,只是给相应的数据打标签;具体要取几分之几的数据,需要再嵌套一层根据标签取出。
SELECT
cookieid,
createtime,
pv,
NTILE(2) OVER(PARTITION BY cookieid ORDER BY createtime) AS rn1,
NTILE(3) OVER(PARTITION BY cookieid ORDER BY createtime) AS rn2,
NTILE(4) OVER(ORDER BY createtime) AS rn3
FROM test_t2
ORDER BY cookieid,createtime;
其他一些窗口函数
lag,lead,first_value,last_value
LAG
LAG(col,n,DEFAULT) 用于统计窗口内往上第n行值第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为NULL时候,取默认值,如不指定,则为NULL)
SELECT cookieid,
createtime,
url,
ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn,
LAG(createtime,1,'1970-01-01 00:00:00') OVER(PARTITION BY cookieid ORDER BY createtime) AS last_1_time,
LAG(createtime,2) OVER(PARTITION BY cookieid ORDER BY createtime) AS last_2_time
FROM test_t4;
last_1_time: 指定了往上第1行的值,default为'1970-01-01 00:00:00'
cookie1第一行,往上1行为NULL,因此取默认值 1970-01-01 00:00:00
cookie1第三行,往上1行值为第二行值,2015-04-10 10:00:02
cookie1第六行,往上1行值为第五行值,2015-04-10 10:50:01
last_2_time: 指定了往上第2行的值,为指定默认值
cookie1第一行,往上2行为NULL
cookie1第二行,往上2行为NULL
cookie1第四行,往上2行为第二行值,2015-04-10 10:00:02
cookie1第七行,往上2行为第五行值,2015-04-10 10:50:01
LEAD
与LAG相反LEAD(col,n,DEFAULT) 用于统计窗口内往下第n行值第一个参数为列名,第二个参数为往下第n行(可选,默认为1),第三个参数为默认值(当往下第n行为NULL时候,取默认值,如不指定,则为NULL)
SELECT cookieid,
createtime,
url,
ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn,
LEAD(createtime,1,'1970-01-01 00:00:00') OVER(PARTITION BY cookieid ORDER BY createtime) AS next_1_time,
LEAD(createtime,2) OVER(PARTITION BY cookieid ORDER BY createtime) AS next_2_time
FROM test_t4;
FIRST_VALUE
取分组内排序后,截止到当前行,第一个值
SELECT cookieid,
createtime,
url,
ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn,
FIRST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime) AS first1
FROM test_t4;
LAST_VALUE
取分组内排序后,截止到当前行,最后一个值
SELECT cookieid,
createtime,
url,
ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn,
LAST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime) AS last1
FROM test_t4;
如果想要取分组内排序后最后一个值,则需要变通一下:
SELECT cookieid,
createtime,
url,
ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn,
LAST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime) AS last1,
FIRST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime DESC) AS last2
FROM test_t4
ORDER BY cookieid,createtime;
特别注意order by
如果不指定ORDER BY,则进行排序混乱,会出现错误的结果
SELECT cookieid,
createtime,
url,
FIRST_VALUE(url) OVER(PARTITION BY cookieid) AS first2
FROM test_t4;
cume_dist,percent_rank
这两个序列分析函数不是很常用,注意:序列函数不支持WINDOW子句
数据准备
d1,user1,1000
d1,user2,2000
d1,user3,3000
d2,user4,4000
d2,user5,5000
CREATE EXTERNAL TABLE test_t3 (
dept STRING,
userid string,
sal INT
) ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
stored as textfile;
加载数据:
load data local inpath '/root/hivedata/test_t3.dat' into table test_t3;
CUME_DIST 和order byd的排序顺序有关系
CUME_DIST 小于等于当前值的行数/分组内总行数 order 默认顺序 正序 升序 比如,统计小于等于当前薪水的人数,所占总人数的比例
SELECT
dept,
userid,
sal,
CUME_DIST() OVER(ORDER BY sal) AS rn1,
CUME_DIST() OVER(PARTITION BY dept ORDER BY sal) AS rn2
FROM test_t3;
rn1: 没有partition,所有数据均为1组,总行数为5,
第一行:小于等于1000的行数为1,因此,1/5=0.2
第三行:小于等于3000的行数为3,因此,3/5=0.6
rn2: 按照部门分组,dpet=d1的行数为3,
第二行:小于等于2000的行数为2,因此,2/3=0.6666666666666666
PERCENT_RANK
PERCENT_RANK 分组内当前行的RANK值-1/分组内总行数-1
经调研 该函数显示现实意义不明朗 有待于继续考证
SELECT
dept,
userid,
sal,
PERCENT_RANK() OVER(ORDER BY sal) AS rn1, --分组内
RANK() OVER(ORDER BY sal) AS rn11, --分组内RANK值
SUM(1) OVER(PARTITION BY NULL) AS rn12, --分组内总行数
PERCENT_RANK() OVER(PARTITION BY dept ORDER BY sal) AS rn2
FROM test_t3;
rn1: rn1 = (rn11-1) / (rn12-1)
第一行,(1-1)/(5-1)=0/4=0
第二行,(2-1)/(5-1)=1/4=0.25
第四行,(4-1)/(5-1)=3/4=0.75
rn2: 按照dept分组,
dept=d1的总行数为3
第一行,(1-1)/(3-1)=0
第三行,(3-1)/(3-1)=1
grouping sets,grouping__id,cube,rollup
这几个分析函数通常用于OLAP中,不能累加,而且需要根据不同维度上钻和下钻的指标统计,比如,分小时、天、月的UV数。
数据准备
2020-03,2020-03-10,cookie1
2020-03,2020-03-10,cookie5
2020-03,2020-03-12,cookie7
2020-04,2020-04-12,cookie3
2020-04,2020-04-13,cookie2
2020-04,2020-04-13,cookie4
2020-04,2020-04-16,cookie4
2020-03,2020-03-10,cookie2
2020-03,2020-03-10,cookie3
2020-04,2020-04-12,cookie5
2020-04,2020-04-13,cookie6
2020-04,2020-04-15,cookie3
2020-04,2020-04-15,cookie2
2020-04,2020-04-16,cookie1
CREATE TABLE test_t5 (
month STRING,
day STRING,
cookieid STRING
) ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
stored as textfile;
加载数据:
load data local inpath '/root/hivedata/test_t5.dat' into table test_t5;
GROUPING SETS
grouping sets是一种将多个group by 逻辑写在一个sql语句中的便利写法。
等价于将不同维度的GROUP BY结果集进行UNION ALL。
GROUPING__ID,表示结果属于哪一个分组集合。
SELECT
month,
day,
COUNT(DISTINCT cookieid) AS uv,
GROUPING__ID
FROM test_t5
GROUP BY month,day
GROUPING SETS (month,day)
ORDER BY GROUPING__ID;
grouping_id表示这一组结果属于哪个分组集合,
根据grouping sets中的分组条件month,day,1是代表month,2是代表day
等价于
SELECT month,NULL,COUNT(DISTINCT cookieid) AS uv,1 AS GROUPING__ID FROM test_t5 GROUP BY month UNION ALL
SELECT NULL as month,day,COUNT(DISTINCT cookieid) AS uv,2 AS GROUPING__ID FROM test_t5 GROUP BY day;
再如:
SELECT
month,
day,
COUNT(DISTINCT cookieid) AS uv,
GROUPING__ID
FROM test_t5
GROUP BY month,day
GROUPING SETS (month,day,(month,day))
ORDER BY GROUPING__ID;
等价于
SELECT month,NULL,COUNT(DISTINCT cookieid) AS uv,1 AS GROUPING__ID FROM test_t5 GROUP BY month
UNION ALL
SELECT NULL,day,COUNT(DISTINCT cookieid) AS uv,2 AS GROUPING__ID FROM test_t5 GROUP BY day
UNION ALL
SELECT month,day,COUNT(DISTINCT cookieid) AS uv,3 AS GROUPING__ID FROM test_t5 GROUP BY month,day;
CUBE
根据GROUP BY的维度的所有组合进行聚合。
SELECT
month,
day,
COUNT(DISTINCT cookieid) AS uv,
GROUPING__ID
FROM test_t5
GROUP BY month,day
WITH CUBE
ORDER BY GROUPING__ID;
等价于
SELECT NULL,NULL,COUNT(DISTINCT cookieid) AS uv,0 AS GROUPING__ID FROM test_t5
UNION ALL
SELECT month,NULL,COUNT(DISTINCT cookieid) AS uv,1 AS GROUPING__ID FROM test_t5 GROUP BY month
UNION ALL
SELECT NULL,day,COUNT(DISTINCT cookieid) AS uv,2 AS GROUPING__ID FROM test_t5 GROUP BY day
UNION ALL
SELECT month,day,COUNT(DISTINCT cookieid) AS uv,3 AS GROUPING__ID FROM test_t5 GROUP BY month,day;
ROLLUP
是CUBE的子集,以最左侧的维度为主,从该维度进行层级聚合。
比如,以month维度进行层级聚合:
SELECT
month,
day,
COUNT(DISTINCT cookieid) AS uv,
GROUPING__ID
FROM test_t5
GROUP BY month,day
WITH ROLLUP
ORDER BY GROUPING__ID;
--把month和day调换顺序,则以day维度进行层级聚合:
SELECT
day,
month,
COUNT(DISTINCT cookieid) AS uv,
GROUPING__ID
FROM test_t5
GROUP BY day,month
WITH ROLLUP
ORDER BY GROUPING__ID;
(这里,根据天和月进行聚合,和根据天聚合结果一样,因为有父子关系,如果是其他维度组合的话,就会不一样)
(把Hive中的数据备份到磁盘中,从磁盘中恢复到Hive中):
通过INSERT OVERWRITE LOCAL DIRECTORY将Hive数据备份到磁盘。
use my_table;
insert overwrite local directory select * from my_source_table;
通过LOAD DATA LOCAL INPATH来加载磁盘数据到Hive。
Hive在HDFS目录的结构
Hive的HDFS根目录是/usr/hive;Hive内部表都属于缺省库default,HDFS目录是/usr/hive/warehouse/
presto可视化客户端使用了yanagishima
导入数据:MySQL、Oracle导入数据到Hadoop的HDFS、Hive、HBASE等数据存储结构。
导出数据:从Hadoop的文件系统中导出数据到关系数据库MySQL等。
官网:https://spark.apache.org/
github: https://github.com/apache/spark
JDK和Scala安装成功(省略安装过程):
java -version
java version "1.8.0_261"
Java(TM) SE Runtime Environment (build 1.8.0_261-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.261-b12, mixed mode)
scala
Welcome to Scala 2.13.3 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_261).
Type in expressions for evaluation. Or try :help.
scala>
从官网下载Spark
chmod 755 spark-3.0.1-bin-hadoop2.7.tgz
tar -xzvf spark-3.0.1-bin-hadoop2.7.tgz
vim ~/.bash_profile
添加如下配置:
export SPARK_HOME=$HOME/install/spark-1.2.0-bin-hadoop1
cd conf/
ls
fairscheduler.xml.template slaves.template
log4j.properties.template spark-defaults.conf.template
metrics.properties.template spark-env.sh.template
cp spark-env.sh.template spark-env.sh
ls
fairscheduler.xml.template spark-defaults.conf.template
log4j.properties.template spark-env.sh
metrics.properties.template spark-env.sh.template
slaves.template
vim spark-env.sh
添加如下配置:
export SPARK_MASTER_IP=127.0.0.1
export SPARK_LOCAL_IP=127.0.0.1
cd到spark的bin
./spark-shell
RDD依赖关系
窄依赖(narrow dependency):map,filter,union,join with inputs co-partitioned
宽依赖(wide dependency):groupByKey,join with inputs not co-partitioned
RDD缓存机制
RDD通过persist方法或cache方法可以将前面的计算结果缓存,但是并不是这两个方法被调用时立即缓存,而是触发后面的action时,该RDD将会被缓存在计算节点的内存中,并供后面重用。cache最终也是调用persist方法,默认的存储级别都是仅在内存存储一份。
缓存有可能丢失,或者存储于内存的数据由于内存不足而被删除,有了RDD的缓存容错机制,即使缓存丢失也能保证计算的正确执行。通过基于RDD的一系列转换,丢失的数据会被重算,由于RDD的各个Partition是相对独立的,因此只需计算丢失的部分即可,并不需要重算全部Partition。
DAG生成
对于宽依赖,由于有Shuffle的存在,只能在parent RDD处理完成后,才能开始接下来的计算,因此宽依赖是划分Stage的依据。
对于窄依赖,partition的转换处理在Stage中完成计算。
DAG调度
DAGScheduler
TaskScheduler
Spark 运行原理 & 工作机制
1)构建Application的运行环境,Driver创建一个SparkContext
2)SparkContext向资源管理器(Standalone、Mesos、Yarn)申请Executor资源,资源管理器启动StandaloneExecutorbackend(Executor)
3) Executor向SparkContext申请Task
4)SparkContext将应用程序分发给Executor
5)SparkContext就建成DAG图,DAGScheduler将DAG图解析成Stage,每个Stage有多个task,形成taskset发送给TaskScheduler,由TaskScheduler将Task发送给Executor运行
6)Task在Executor上运行,运行完释放所有资源
Dataset & DataFrame
Spark 1.3 的时候做了一个重大变革。就是将 SchemaRDD 重命名为 DataFrame,主要原因是 DataFrame 不再直接继承自 RDD,而是自己维护和实现了自己的功能函数。但是 DataFrame 可以通过调用 .rdd 转化为 RDD。
Spark 1.6 的时候也是有了重大调整,增加了 Dataset 的概念,类似 RDD,在享受 Spark SQL 执行引擎性能优化的同时允许用户使用自定义对象和 lambda 函数。在引入 Dataset 的同时,也引入了 SparkSession,也即是会话管理功能,允许不同用户可以在使用不同配置和临时表的情况下共享统一的集群。
Spark 2.0 开始,Dataset API 和 Dataframe API 统一了。Scala 版本,DataFrame 被类型定义成 Dataset[Row],Java 版本必须是要 Dataset[Row] 代替Dataframe。SparkSession 已经完全替换掉了旧的 SQLContext 和 HiveContext。SQLContext 和 HiveContext 为了保持兼容还在被保留。2.0 还上线了 Structured Streaming,这个是 Spark 流处理发展的主要方向,底层是基于 Spark SQL 和 Catalyst 优化器,让用户像使用静态 Dataset 开发离线处理任务一样使用流 Dataset 开发流处理业务,这个就是依赖于 Catalyst 优化器自动增量的查询计划。
SparkSession & SparkContext & SQLContext & HiveContext
SparkSession
SparkSession是对Spark计算集群的一个连接,SparkSession是在Spark 2.0中引入的,它使开发人员可以轻松地使用它,这样我们就不用担心不同的上下文,并简化了对不同上下文的访问。通过访问SparkSession,我们可以自动访问SparkContext。在2.x之前,对于不同的功能,需要使用不同的Context
创建和操作RDD时,使用SparkContext
使用Streaming时,使用StreamingContext
使用SQL时,使用SQLContext
使用Hive时,使用HiveContext
SparkSession内部封装了SparkContext,所以计算实际上是由SparkContext完成的。
下面是如何创建一个SparkSession
val spark = SparkSession
.builder()
.appName("SparkSessionTest")
.config("spark.xxx.option", "option-value")
.getOrCreate()
SparkSession现在是Spark的新入口点,它替换了旧的SQLContext和HiveContext。注意,保留旧的SQLContext和HiveContext是为了向后兼容。
一旦我们访问了SparkSession,我们就可以开始使用DataFrame和Dataset了。
下面是我们如何使用Hive支持创建SparkSession。
val spark = SparkSession
.builder()
.appName("SparkSessionHiveTest")
.config("spark.sql.warehouse.dir", warehouseLocation)
.enableHiveSupport()
.getOrCreate()
因此,如果您正在使用Spark 2.0或更高版本,建议使用SparkSession。
spark-shell时,SparkContext as 'sc',SparkSession as 'spark'也默认已经有:
SparkContext
创建SparkContext时可以创建SparkConf
//set up the spark configuration
val sparkConf = new SparkConf().setAppName("SparkContextTest").setMaster("local[2]")
//get SparkContext using the SparkConf
val sc = new SparkContext(sparkConf)
SQLContext
SQLContext是通往SparkSQL的入口。下面是如何使用SparkContext创建SQLContext。
val sqlContext = new org.apache.spark.sql.SQLContext(sc)
一旦有了SQLContext,就可以开始处理DataFrame、DataSet等。
HiveContext
HiveContext是通往Hive入口。HiveContext具有SQLContext的所有功能。
实际上,如果查看API文档,就会发现HiveContext扩展了SQLContext,这意味着它支持SQLContext支持的功能以及更多(Hive特定的功能)
public class HiveContext extends SQLContext implements Logging
下面是如何使用SparkContext获得HiveContext
val sqlContext = new org.apache.spark.sql.hive.HiveContext(sc)
Spark SQL
三大功能:
(1) Spark SQL 可以从各种结构化数据源(例如 JSON、 Hive、 Parquet 等)中读取数据。
(2) Spark SQL 既支持在 Spark 程序内使用 SQL 语句进行数据查询,又支持从 Tableau 等商业智能软件外部工具中通过标准数据库连接器(JDBC/ODBC)连接 Spark SQL 进行查询。
(3) Spark SQL 支持 SQL 与常规的 Python/Java/Scala 代码高度整合,包括连接 RDD 与 SQL 表、公开的自定义 SQL 函数接口等。
用户自定义函数 UDF:
可以让我们使用 Python/Java/Scala 注册自定义函数,并在 SQL 中调用,这种方法很常用,通常用来给机构内的 SQL 用户们提供高级功能支持,这样这些用户就可以直接调用注册的函数而无需自己去通过编程来实现了。Spark SQL 不仅有自己的 UDF 接口,也支持已有的 Apache Hive UDF。
Spark Streaming
Spark Streaming 使用离散化流(discretized stream)作为抽象表示, 叫作 DStream。
DStream 是随时间推移而收到的数据的序列。在内部,每个时间区间收到的数据都作为 RDD 存在,而 DStream 是由这些 RDD 所组成的序列(因此得名“离散化”)。DStream 可以从各种输入源创建,比如 Flume、 Kafka 或者 HDFS。创建出来的 DStream 支持两种操作,一种是转化操作(transformation),会生成一个新的DStream,另一种是输出操作(output operation),可以把数据写入外部系统中。DStream 提供了许多与 RDD 所支持的操作相类似的操作支持,还增加了与时间相关的新操作,比如滑动窗口。
(1) 转化操作
DStream 的转化操作可以分为无状态(stateless)和有状态(stateful)两种。
DStream 无状态转化操作的例子(不完整列表):
DStream 的有状态转化操作是跨时间区间跟踪数据的操作;也就是说,一些先前批次的数据也被用来在新的批次中计算结果。 主要的两种类型是滑动窗口和 updateStateByKey(),前者以一个时间阶段为滑动窗口进行操作, 后者则用来跟踪每个键的状态变化 (例如构建一个代表用户会话的对象)。有状态转化操作需要在你的 StreamingContext 中打开检查点机制来确保容错性。
(2) 检查点(checkpoint)机制
Spark与Hadoop对比
(省略Spark图计算GraphX和机器学习MLlib)