本文是基于CentOS 7.3系统环境,进行hive的学习和使用
Hive是用于解决海量结构化日志的数据统计工具,是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类SQL查询功能
Hive的本质就是将HQL转化成MapReduce程序
Hive通过给用户提供的一系列交互接口,接收到用户的指令(SQL),使用自己的Driver,结合元数据(MetaStore),将这些指令翻译成MapReduce,提交到Hadoop中执行,最后,将执行返回的结果输出到用户交互接口。
由于 Hive 采用了类似SQL 的查询语言 HQL(Hive Query Language),因此很容易将 Hive 理解为数据库。其实从结构上来看,Hive 和数据库除了拥有类似的查询语言,再无类似之处。本文将从多个方面来阐述 Hive 和数据库的差异。数据库可以用在 Online 的应用中,但是Hive 是为数据仓库而设计的,清楚这一点,有助于从应用角度理解 Hive 的特性。
apache-hive-1.2.1-bin.tar.gz
tar -xzvf apache-hive-1.2.1-bin.tar.gz -C /opt/module
cd /opt/module
mv apache-hive-1.2.1-bin hive
vi /etc/profile
# 添加如下内容
#HIVE_HOME
export HIVE_HOME=/opt/module/hive
export PATH=$PATH:$HIVE_HOME/bin
cd /opt/module/hive/conf
cp hive-env.sh.template hive-env.sh
vi hive-env.sh
# 添加如下内容
# Set HADOOP_HOME to point to a specific hadoop install directory
HADOOP_HOME=/opt/module/hadoop-2.7.2
# Hive Configuration Directory can be controlled by:
export HIVE_CONF_DIR=/opt/module/hive/conf
hive
# 创建数据库
create database test;
# 创建数据表
create table student(id int, name string);
# 插入数据
insert into table student values(1001, "zhangsan");
# 查询数据
select * from student;
# 删除数据表
drop table student;
# 删除数据库
drop database test;
hive默认存储元数据的数据库为derby,不支持并发访问,多开几个hive客户端会出现异常
hive默认存储元数据的数据库为derby,不支持并发访问,多开几个hive客户端会出现异常,因此需要安装MySQL数据库来替换
CentOS 7离线安装MySQL 5.6
cd /opt/module/hive/conf
vi hive-site.xml
# 添加如下内容
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://192.168.1.101:3306/metastore?createDatabaseIfNotExist=true</value>
<description>JDBC connect string for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
<description>Driver class name for a JDBC metastore</description>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
<description>username to use against metastore database</description>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>123456</value>
<description>password to use against metastore database</description>
</property>
</configuration>
hive
cd /opt/module/hive/bin
./hiveserver2
打开另一个终端
cd /opt/module/hive/bin
./beeline
!connect jdbc:hive2://hadoop101:10000
# 只需输入hadoop的用户名,不需要密码
cd /opt/module/hive
bin/hive -e "select * from test.student;"
bin/hive -e "select * from test.student;">result.log
cd /opt/module/hive
vi test.sql
# 添加如下内容
select * from test.student;
# 执行下面命令
bin/hive -f test.sql>result.log
quit;
cd /opt/module/hive/conf
vi hive-site.xml
# 添加如下内容
<property>
<name>hive.metastore.warehouse.dir</name>
<value>/user/hive/warehouse</value>
<description>location of default database for the warehouse</description>
</property>
cd /opt/module/hive/conf
vi hive-site.xml
# 添加如下内容
<property>
<name>hive.cli.print.header</name>
<value>true</value>
</property>
<property>
<name>hive.cli.print.current.db</name>
<value>true</value>
</property>
cd /opt/module/hive/conf
cp hive-log4j.properties.template hive-log4j.properties
vi hive-log4j.properties
# 添加如下内容
hive.log.dir=/opt/module/hive/logs
hive数据类型 | java数据类型 | 长度 | 示例 |
---|---|---|---|
tinyint | byte | 1byte有符号整数 | 20 |
smalint | short | 2byte有符号整数 | 20 |
int | int | 4byte有符号整数 | 20 |
bigint | long | 8byte有符号整数 | 20 |
boolean | boolean | 布尔类型,true或者false | TRUE FALSE |
float | float | 单精度浮点数 | 3.14159 |
double | double | 双精度浮点数 | 3.14159 |
string | string | 字符系列,可以使用单引号或者双引号 | ‘now is’ “i am a” |
timestamp | 时间类型 | ||
binary | 字节数组 |
数据类型 | 描述 | 语法示例 |
---|---|---|
struct | 和c语言中的struct类似,都可以通过“点”符号访问元素内容。例如,如果某个列的数据类型是STRUCT{first STRING, last STRING},那么第1个元素可以通过字段.first来引用。 | struct() 例如struct |
map | MAP是一组键-值对元组集合,使用数组表示法可以访问数据。例如,如果某个列的数据类型是MAP,其中键->值对是’first’->’John’和’last’->’Doe’,那么可以通过字段名[‘last’]获取最后一个元素 | map() 例如map |
array | 数组是一组具有相同类型和名称的变量的集合。这些变量称为数组的元素,每个数组元素都有一个编号,编号从零开始。例如,数组值为[‘John’, ‘Doe’],那么第2个元素可以通过数组名[1]进行引用。 | Array() 例如array |
vi test.txt
# 添加如下内容
songsong,bingbing_lili,xiao song:18_xiaoxiao song:19,hui long guan_beijing
yangyang,caicai_susu,xiao yang:18_xiaoxiao yang:19,chao yang_beijing
vi test.sql
# 添加如下内容
create table test.test(
name string,
friends array<string>,
children map<string, int>,
address struct<street:string, city:string>
)
row format delimited fields terminated by ','
collection items terminated by '_'
map keys terminated by ':'
lines terminated by '\n';
hdfs dfs -put test.txt /user/hive/warehouse/test.db/test
hive
use test;
select name,friends[1],children["xiao song"],address.city from test;
Hive的原子数据类型是可以进行隐式转换的,类似于Java的类型转换,例如某表达式使用INT类型,TINYINT会自动转换为INT类型,但是Hive不会进行反向转化,例如,某表达式使用TINYINT类型,INT不会自动转换为TINYINT类型,它会返回错误,除非使用CAST操作。
select '1'+2, cast('1'as int) + 2;
CREATE DATABASE [IF NOT EXISTS] database_name
[COMMENT database_comment]
[LOCATION hdfs_path]
[WITH DBPROPERTIES (property_name=property_value, ...)];
create database test1 comment "test1 database" location "/test" with dbproperties("zhangsan"="lisi");
show databases;
show databases like 'test';
desc database test1;
desc database extended test1;
use test1;
alter database test1 set dbproperties('name'='zhangsan');
drop database test1;
drop database if exists test1;
drop database test1 cascade;
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]
[TBLPROPERTIES (property_name=property_value, ...)]
[AS select_statement]
create table student1(id int comment "Identity", age int comment "Age") comment "Student" row format delimited fields terminated by '\t' location '/student';
desc student1;
desc formatted student1;
管理表(managed_table)
删除表后,存储在HDFS上的数据也会被删除
外部表(external_table)
删除表后,存储在HDFS上的数据不会被删除
alter table student1 set tblproperties('EXTERNAL'='TRUE');
alter table student2 set tblproperties('EXTERNAL'='FALSE');
1. 新建表
create table dept_partition(deptno int, dname string, loc string)
partitioned by (month string)
row format delimited fields terminated by '\t';
2. 加载数据
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201709');
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201708');
hive (default)> load data local inpath '/opt/module/datas/dept.txt' into table default.dept_partition partition(month='201707');
3. 查询表数据
select * from dept_partition where month='201709';
4. 联合查询表数据
select * from dept_partition where month='201709' union
select * from dept_partition where month='201708' union
select * from dept_partition where month='201707';
hive (default)> alter table dept_partition add partition(month='201705') partition(month='201704');
hive (default)> alter table dept_partition drop partition(month='201705'), partition(month='201704');
show partitions dept_partition;
desc formatted dept_partition;
1. 新建表
create table dept_partition2(deptno int, dname string, loc string)
partitioned by (month string, day string)
row format delimited fields terminated by '\t';
2. 加载数据
load data local inpath '/opt/module/datas/dept.txt' into table
default.dept_partition2 partition(month='201709', day='13');
msck repair table dept_partition2;
alter table dept_partition2 rename to dept_partition3;
alter table dept_partition add columns(deptdesc string);
alter table dept_partition change column deptdesc desc int;
alter table dept_partition replace columns(deptno string, dname
string, loc string);
load data [local] inpath '/opt/module/datas/student.txt' [overwrite] into table student [partition (partcol1=val1,…)];
# local:表示从本地加载数据到hive表;否则从HDFS加载数据到hive表
# overwrite:表示覆盖表中已有数据,否则表示追加
# 基本插入
insert into table student values(1,'wangwu'),(2,'zhaoliu');
# 查询插入
insert overwrite table student
select id, name from student where id>10;
create table if not exists student3 as select id, name from student;
上传数据至HDFS
hive (default)> dfs -mkdir /student;
hive (default)> dfs -put /opt/module/datas/student.txt /student;
创建表,并指定HDFS上的位置
create external table if not exists student5(id int, name string)
row format delimited fields terminated by '\t'
location '/student;
查询数据
hive (default)> select * from student5;
# 先用export导出后,再将数据导入
import table student2 from '/user/hive/warehouse/export/student';
# 导出到本地
insert overwrite local directory '/opt/module/datas/export/student1'
row format delimited fields terminated by '\t'
select * from student;
# 导出到HDFS
insert overwrite directory '/user/xuzheng/student2'
row format delimited fields terminated by '\t'
select * from student;
hive (default)> dfs -get /user/hive/warehouse/student/month=201709/000000_0
/opt/module/datas/export/student3.txt;
bin/hive -e 'select * from default.student;' > /opt/module/datas/export/student4.txt;
export和import主要用于两个Hadoop平台集群之间Hive表迁移
# 既能导出元数据,也能导出数据
export table default.student to '/user/hive/warehouse/export/student';
# Truncate只能删除管理表,不能删除外部表中数据
truncate table student;
# 创建部门表
create table if not exists dept(deptno int, dname string, loc int)
row format delimited fields terminated by '\t';
# 创建员工表
create table if not exists emp(empno int, ename string, job string, mgr int, hiredate string, sal double, comm double, deptno int)
row format delimited fields terminated by '\t';
# 向部门表导入数据
load data local inpath '/home/xuzheng/dept.txt' into table
dept;
# 向员工表导入数据
load data local inpath '/home/xuzheng/emp.txt' into table emp;
# 全表查询
select * from emp;
# 特定列查询
select empno, ename from emp;
select ename as name, deptno dn from emp;
运算符 | 描述 |
---|---|
A + B | A和B相加 |
A - B | A和B相减 |
A * B | A和B相乘 |
A / B | A和B相除 |
A % B | A对B取余 |
A & B | A和B按位取余 |
A|B | A和B按位取或 |
A ^ B | A和B按位取异或 |
~A | A按位取反 |
select sal +1 from emp;
# 求总行数
select count(*) cnt from emp;
# 求最大值
select max(sal) max_sal from emp;
# 求最小值
select min(sal) min_sal from emp;
# 求总和
select sum(sal) sum_sal from emp;
# 求平均值
select avg(sal) avg_sal from emp;
select * from emp limit 5;
# where子句中不能使用字段别名
select * from emp where sal >1000;
操作符 | 支持的数据类型 | 描述 |
---|---|---|
A = B | 基本数据类型 | 如果A等于B则返回TRUE,反之返回FALSE |
A <=> B | 基本数据类型 | 如果A和B都为NULL,则返回TRUE,其他的和等号(=)操作符的结果一致,如果任一为NULL则结果为NULL |
A<>B, A!=B | 基本数据类型 | A或者B为NULL则返回NULL;如果A不等于B,则返回TRUE,反之返回FALSE |
A | 基本数据类型 | A或者B为NULL,则返回NULL;如果A小于B,则返回TRUE,反之返回FALSE |
A<=B | 基本数据类型 | A或者B为NULL,则返回NULL;如果A小于等于B,则返回TRUE,反之返回FALSE |
A>B | 基本数据类型 | A或者B为NULL,则返回NULL;如果A大于B,则返回TRUE,反之返回FALSE |
A>=B | 基本数据类型 | A或者B为NULL,则返回NULL;如果A大于等于B,则返回TRUE,反之返回FALSE |
A [NOT] BETWEEN B AND C | 基本数据类型 | 如果A,B或者C任一为NULL,则结果为NULL。如果A的值大于等于B而且小于或等于C,则结果为TRUE,反之为FALSE。如果使用NOT关键字则可达到相反的效果。 |
A IS NULL | 所有数据类型 | 如果A等于NULL,则返回TRUE,反之返回FALSE |
A IS NOT NULL | 所有数据类型 | 如果A不等于NULL,则返回TRUE,反之返回FALSE |
IN(数值1, 数值2) | 所有数据类型 | 使用 IN运算显示列表中的值 |
A [NOT] LIKE B | STRING 类型 | B是一个SQL下的简单正则表达式,也叫通配符模式,如果A与其匹配的话,则返回TRUE;反之返回FALSE。B的表达式说明如下:‘x%’表示A必须以字母‘x’开头,‘%x’表示A必须以字母’x’结尾,而‘%x%’表示A包含有字母’x’,可以位于开头,结尾或者字符串中间。如果使用NOT关键字则可达到相反的效果。 |
A RLIKE B, A REGEXP B | STRING 类型 | B是基于java的正则表达式,如果A与其匹配,则返回TRUE;反之返回FALSE。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。例如,正则表达式必须和整个字符串A相匹配,而不是只需与其字符串匹配。 |
# 查询出薪水等于5000的所有员工
select * from emp where sal = 5000;
# 查询工资在500到1000的员工信息
select * from emp where sal between 500 and 1000;
# 查询comm为空的所有员工信息
select * from emp where comm is null;
# 查询工资是1500或5000的员工信息
select * from emp where sal IN (1500, 5000);
正则匹配 | 描述 |
---|---|
\ | 转义 |
^ | 一行的开头 |
^R | 匹配以R为开头的行 |
$ | 匹配一行的结尾 |
R$ | 匹配以R为结尾的行 |
* | 表示上一个子式匹配0次或多次,贪心匹配 |
Zo* | Zo Zoo Zooo |
. | 匹配一个任意的字符 |
.* | 匹配任意字符串 |
[] | 匹配某个范围内的字符 |
[a-z] | 匹配一个a-z之间的字符 |
[a-z]* | 匹配任意字母字符串 |
# 查找以2开头薪水的员工信息
select * from emp where sal LIKE '2%';
# 查找第二个数值为2的薪水的员工信息
select * from emp where sal LIKE '_2%';
# 查找薪水中含有2的员工信息
select * from emp where sal RLIKE '[2]';
操作符 | 描述 |
---|---|
and | 逻辑并 |
or | 逻辑或 |
not | 逻辑否 |
# 查询薪水大于1000,部门是30
select * from emp where sal>1000 and deptno=30;
# 查询薪水大于1000,或者部门是30
select * from emp where sal>1000 or deptno=30;
# 查询除了20部门和30部门以外的员工信息
select * from emp where deptno not IN(30, 20);
# 计算emp表每个部门的平均工资
select t.deptno, avg(t.sal) avg_sal from emp t group by t.deptno;
# 计算emp每个部门中每个岗位的最高薪水
select t.deptno, t.job, max(t.sal) max_sal from emp t group by
t.deptno, t.job;
# 求每个部门的平均工资
select deptno, avg(sal) from emp group by deptno;
# 求每个部门的平均薪水大于2000的部门
select deptno, avg(sal) avg_sal from emp group by deptno having
avg_sal > 2000;
# 根据员工表和部门表中的部门编号相等,查询员工编号、员工名称和部门名称;
select e.empno, e.ename, d.deptno, d.dname from emp e join dept d on e.deptno = d.deptno;
# 合并员工表和部门表
select e.empno, e.ename, d.deptno from emp e join dept d on e.deptno = d.deptno;
# 只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来
select e.empno, e.ename, d.deptno from emp e join dept d on e.deptno = d.deptno;
# JOIN操作符左边表中符合WHERE子句的所有记录将会被返回
select e.empno, e.ename, d.deptno from emp e left join dept d on e.deptno = d.deptno;
# JOIN操作符右边表中符合WHERE子句的所有记录将会被返回
select e.empno, e.ename, d.deptno from emp e right join dept d on e.deptno = d.deptno;
# 将会返回所有表中符合WHERE语句条件的所有记录。如果任一表的指定字段没有符合条件的值的话,那么就使用NULL值替代
select e.empno, e.ename, d.deptno from emp e full join dept d on e.deptno = d.deptno;
create table if not exists location(loc int, loc_name string)
row format delimited fields terminated by '\t';
load data local inpath '/home/xuzheng/location.txt' into table location;
SELECT e.ename, d.dname, l.loc_name
FROM emp e
JOIN dept d
ON d.deptno = e.deptno
JOIN location l
ON d.loc = l.loc;
hive中严禁使用笛卡尔积
hive join目前不支持在on子句中使用谓词or
# 查询员工信息按工资升序排列
select * from emp order by sal;
# 查询员工信息按工资降序排列
select * from emp order by sal desc;
# 按照员工薪水的2倍排序
select ename, sal*2 twosal from emp order by twosal;
# 按照部门和工资升序排序
select ename, deptno, sal from emp order by deptno, sal;
Sort By:对于大规模的数据集order by的效率非常低。在很多情况下,并不需要全局排序,此时可以使用sort by,按照分区排序。
Sort by为每个reducer产生一个排序文件。每个Reducer内部进行排序,对全局结果集来说不是排序。
# 设置reduce个数
set mapreduce.job.reduces=3;
# 查看设置reduce个数
set mapreduce.job.reduces;
# 根据部门编号降序查看员工信息
select * from emp sort by deptno desc;
# 将查询结果导入到文件中(按照部门编号降序排序)
insert overwrite local directory '/home/xuzheng/datas/sortby-result' select * from emp sort by deptno desc;
Distribute By: 在有些情况下,我们需要控制某个特定行应该到哪个reducer,通常是为了进行后续的聚集操作。distribute by 子句可以做这件事。distribute by类似MR中partition(自定义分区),进行分区,结合sort by使用。
对于distribute by进行测试,一定要分配多reduce进行处理,否则无法看到distribute by的效果。
# 设置reduce个数
set mapreduce.job.reduces=3;
# 先按照部门编号分区,再按照员工编号降序排序
select * from emp distribute by deptno sort by empno desc;
当distribute by和sorts by字段相同时,可以使用cluster by方式
cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是升序排序,不能指定排序规则为ASC或者DESC
# 按照部门编号分区排序
select * from emp cluster by deptno;
# 与上面语句等价
select * from emp distribute by deptno sort by deptno;
create table stu_buck(id int, name string)
clustered by(id)
into 4 buckets
row format delimited fields terminated by '\t';
create table stu(id int, name string)
row format delimited fields terminated by '\t';
load data local inpath '/home/xuzheng/student.txt' into table stu;
set hive.enforce.bucketing=true;
# 让hive自己去决定分桶个数
set mapreduce.job.reduces=-1;
insert into stu_buck select * from stu;
tablesample((bucket x out of y)
y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。例如,table总共分了4份,当y=2时,抽取(4/2=)2个bucket的数据,当y=8时,抽取(4/8=)1/2个bucket的数据
# 按照id抽样查询,将数据分4份,每一份取第1个数据
select * from stu_buck tablesample(bucket 1 out of 4 on id);
# 如果员工的comm为NULL,则用-1代替
select comm,nvl(comm, -1) from emp;
# 如果员工的comm为NULL,则用领导id代替
select comm, nvl(comm,mgr) from emp;
姓名 | 部门 | 性别 |
---|---|---|
悟空 | A | 男 |
大海 | A | 男 |
宋宋 | B | 男 |
凤姐 | A | 女 |
婷姐 | B | 女 |
婷婷 | B | 女 |
create table emp_sex(name string, dept_id string, sex string)
row format delimited fields terminated by "\t";
load data local inpath '/home/xuzheng/emp_sex.txt' into table emp_sex;
# 求出不同部门男女各多少人。结果如下:
select
dept_id,
sum(case sex when '男' then 1 else 0 end) male_count,
sum(case sex when '女' then 1 else 0 end) female_count
from
emp_sex
group by
dept_id;
姓名 | 星座 | 血型 |
---|---|---|
孙悟空 | 白羊座 | A |
大海 | 射手座 | A |
宋宋 | 白羊座 | B |
猪八戒 | 白羊座 | A |
凤姐 | 射手座 | A |
射手座,A 大海|凤姐
白羊座,A 孙悟空|猪八戒
白羊座,B 宋宋|苍老师
vi constellation.txt
孙悟空 白羊座 A
大海 射手座 A
宋宋 白羊座 B
猪八戒 白羊座 A
凤姐 射手座 A
create table person_info(name string, constellation string, blood_type string)
row format delimited fields terminated by "\t";
load data local inpath "/home/xuzheng/constellation.txt" into table person_info;
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;
电源 | 分类 |
---|---|
《疑犯追踪》 | 悬疑,动作,科幻,剧情 |
《Lie to me》 | 悬疑,警匪,动作,心理,剧情 |
《战狼2》 | 战争,动作,灾难 |
《疑犯追踪》 悬疑
《疑犯追踪》 动作
《疑犯追踪》 科幻
《疑犯追踪》 剧情
《Lie to me》 悬疑
《Lie to me》 警匪
《Lie to me》 动作
《Lie to me》 心理
《Lie to me》 剧情
《战狼2》 战争
《战狼2》 动作
《战狼2》 灾难
vi movie.txt
《疑犯追踪》 悬疑,动作,科幻,剧情
《Lie to me》 悬疑,警匪,动作,心理,剧情
《战狼2》 战争,动作,灾难
create table movie_info(movie string, category array<string>)
row format delimited fields terminated by "\t"
collection items terminated by ",";
load data local inpath "/home/xuzheng/movie.txt" into table movie_info;
select
movie,
category_name
from
movie_info lateral view explode(category) table_tmp as category_name;
姓名 | 购买日期 | 价格 |
---|---|---|
jack | 2017-01-01 | 10 |
tony | 2017-01-02 | 15 |
jack | 2017-02-03 | 23 |
tony | 2017-01-04 | 29 |
jack | 2017-01-05 | 46 |
jack | 2017-04-06 | 42 |
tony | 2017-01-07 | 50 |
jack | 2017-01-08 | 55 |
mart | 2017-04-08 | 62 |
mart | 2017-04-09 | 68 |
neil | 2017-05-10 | 12 |
mart | 2017-04-11 | 75 |
neil | 2017-06-12 | 80 |
mart | 2017-04-13 | 94 |
vi business.txt
create table business(name string, orderdate string,cost int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
load data local inpath "/home/xuzheng/business.txt" into table business;
select name,count(*) over ()
from business
where substring(orderdate,1,7) = '2017-04'
group by name;
select name,orderdate,cost,sum(cost) over(partition by name, month(orderdate)) from business;
select name,orderdate,cost,
sum(cost) over() as sample1,--所有行相加
sum(cost) over(partition by name) as sample2,--按name分组,组内数据相加
sum(cost) over(partition by name order by orderdate) as sample3,--按name分组,组内数据累加
sum(cost) over(partition by name order by orderdate rows between UNBOUNDED PRECEDING and current row ) as sample4 ,--和sample3一样,由起点到当前行的聚合
sum(cost) over(partition by name order by orderdate rows between 1 PRECEDING and current row) as sample5, --当前行和前面一行做聚合
sum(cost) over(partition by name order by orderdate rows between 1 PRECEDING AND 1 FOLLOWING ) as sample6,--当前行和前边一行及后面一行
sum(cost) over(partition by name order by orderdate rows between current row and UNBOUNDED FOLLOWING ) as sample7 --当前行及后面所有行
from business;
select name,orderdate,cost,
lag(orderdate,1,'1900-01-01') over(partition by name order by orderdate ) as time1, lag(orderdate,2) over (partition by name order by orderdate) as time2
from business;
select * from (
select name,orderdate,cost, ntile(5) over(order by orderdate) sorted
from business
) t
where sorted = 1;
姓名 | 科目 | 成绩 |
---|---|---|
孙悟空 | 语文 | 87 |
孙悟空 | 数学 | 95 |
孙悟空 | 英语 | 68 |
大海 | 语文 | 94 |
大海 | 数学 | 56 |
大海 | 英语 | 84 |
宋宋 | 语文 | 64 |
宋宋 | 数学 | 86 |
宋宋 | 英语 | 84 |
婷婷 | 语文 | 65 |
婷婷 | 数学 | 85 |
婷婷 | 英语 | 78 |
vi score.txt
create table score(
name string,
subject string,
score int)
row format delimited fields terminated by "\t";
load data local inpath '/home/xuzheng/score.txt' into table score;
select name,
subject,
score,
rank() over(partition by subject order by score desc) rp,
dense_rank() over(partition by subject order by score desc) drp,
row_number() over(partition by subject order by score desc) rmp
from score;
<dependencies>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>1.2.1</version>
</dependency>
</dependencies>
package com.inspur.hive;
import org.apache.hadoop.hive.ql.exec.UDF;
public class Lower extends UDF {
public int evaluate(String line) {
if (line == null) {
return 0;
} else {
return line.length();
}
}
public int evalute(Number line) {
if (line == null) {
return 0;
} else {
return line.toString().length();
}
}
public int evalute(Boolean line) {
if (line == null) {
return 0;
} else {
return line.toString().length();
}
}
}
add jar /home/xuzheng/1.jar;
create function mylen as "com.inspur.hive.Lower";
select ename, mylen(ename) from emp;
hive (default)>set hive.exec.compress.intermediate=true;
hive (default)>set mapreduce.map.output.compress=true;
hive (default)>set mapreduce.map.output.compress.codec = org.apache.hadoop.io.compress.SnappyCodec;
hive (default)> select count(ename) name from emp;
hive (default)>set hive.exec.compress.output=true;
hive (default)>set mapreduce.output.fileoutputformat.compress=true;
hive (default)> set mapreduce.output.fileoutputformat.compress.codec =
org.apache.hadoop.io.compress.SnappyCodec;
hive (default)> set mapreduce.output.fileoutputformat.compress.type=BLOCK;
hive (default)> insert overwrite local directory
'/home/xuzheng/distribute-result' select * from emp distribute by deptno sort by empno desc;
Hive支持的存储数据的格式主要有:TEXTFILE 、SEQUENCEFILE、ORC、PARQUET
create table log_orc_none(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as orc tblproperties ("orc.compress"="NONE");
insert into table log_orc select * from log_text;
dfs -du -h /user/hive/warehouse/log_orc/;
create table log_orc_snappy(
track_time string,
url string,
session_id string,
referer string,
ip string,
end_user_id string,
city_id string
)
row format delimited fields terminated by '\t'
stored as orc tblproperties ("orc.compress"="SNAPPY");
insert into table log_orc_snappy select * from log_text;
dfs -du -h /user/hive/warehouse/log_orc_snappy/;
Fetch抓取
Hive中对某些情况的查询可以不必使用MapReduce计算。例如:SELECT * FROM employees;在这种情况下,Hive可以简单地读取employee对应的存储目录下的文件,然后输出查询结果到控制台。
Fetch参数配置
<property>
<name>hive.fetch.task.conversion</name>
<value>more</value>
<description>
Expects one of [none, minimal, more].
Some select queries can be converted to single FETCH task minimizing latency.
Currently the query should be single sourced not having any subquery and should not have any aggregations or distincts (which incurs RS), lateral views and joins.
0. none : disable hive.fetch.task.conversion
1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only
2. more : SELECT, FILTER, LIMIT only (support TABLESAMPLE and virtual columns)
</description>
</property>
案例实操1
把hive.fetch.task.conversion设置成none,然后执行查询语句,都会执行mapreduce程序
set hive.fetch.task.conversion=none;
select * from emp;
select ename from emp;
select ename from emp limit 3;
案例实操2
把hive.fetch.task.conversion设置成more,然后执行查询语句,如下查询方式都不会执行mapreduce程序
set hive.fetch.task.conversion=more;
select * from emp;
select ename from emp;
select ename from emp limit 3;
新版的hive已经对小表JOIN大表和大表JOIN小表进行了优化。小表放在左边和右边已经没有明显区别。
测试大表join小表和小表join大表的效率
(1)创建大表
create table bigtable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';
(2)创建小表
create table smalltable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';
(3)创建join后的表
create table jointable(id bigint, time bigint, uid string, keyword string, url_rank int, click_num int, click_url string) row format delimited fields terminated by '\t';
(4)导入数据
load data local inpath '/home/xuzheng/bigtable' into table bigtable;
load data local inpath '/home/xuzheng/smalltable' into table smalltable;
(5)打开mapjoin功能(默认是打开的)
set hive.auto.convert.join = true;
(6)执行小表JOIN大表语句
insert overwrite table jointable
select b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from smalltable s
join bigtable b
on b.id = s.id;
(7)执行结果
MapReduce Total cumulative CPU time: 31 seconds 100 msec
No rows affected (52.897 seconds)
(8)执行大表JOIN小表语句
insert overwrite table jointable
select b.id, b.time, b.uid, b.keyword, b.url_rank, b.click_num, b.click_url
from bigtable b
join smalltable s
on s.id = b.id;
(9)执行结果
MapReduce Total cumulative CPU time: 29 seconds 790 msec
No rows affected (50.443 seconds)
(10)注意
大表放在左边 left join 小表,可以走mapjoin进行优化;
如果使用 join,也就是inner join 大表小表的左右顺序无所谓,都会进行优化