插入(装载)数据
load data [local] inpath 'pathname' [overwrite] into table tablename [partition(column=xxx)]
insert 方法:
insert方法:insert into tablename select xx,xx,xxx,xxx,[union all] select xxx,xxx,xx,xxx;
from table_name insert overwrite table table_name [partition(xx,xx)] select xx,xx,xx; 典型的ETL模式
insert into tablename values(coulmmn1 xxx,coulmn2 xx); 指定列插入
insert into tablename(name) value('Judy') 指定值插入
select 5,‘mm’,‘1994-1-5’,array(‘study’)[union all] select xxx,xxx,xxx,
)
insert into emps select * from t
导入数据csv文件
CREATE EXTERNAL TABLE IF NOT EXISTS products (
product_id int,
product_category_id int,
product_price float,
product_image varchar(255))
ROW FORMAT serde 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
with serdeproperties ("separatorChar"=",")
LOCATION '/data/retail_db/products';
内部表 使用load data inpath ‘/x/x/’ into table table_name
外部表 location 所指定的是文件的文件夹而不是文件
导出数据
export table table_name [partition(xx=xx,xx=xx)] to ‘/root/output’;
创建表
create table tablename as select * from xxx; CTS
create table tablename as with 【结果集】 CTE
create table tablename like tablename; 复制表结构不复制内容
row format serde ‘org.apache.hadoop.hive.serde2.OpenCSVSerde’ 把csv导入
location ‘/shopping/’ 导入的是文件夹,只能放一个文件
tblproperties (“skip.header.line.count”=“1”) 跳过首行
查询数据
单查 select xx from tablename where xxx;
子查询:with a as(select * from tablename where xxx) select * from a;
: select * from (select * from xxx)a;
删除表
drop table if exists employee[with perge]------------------>with perge 直接删除【可选】否则会放在.Trash目录
alter table tabe_name rename to new_table_name; 更改表名
alter table table_name change old_name new_name string; 更改列名
alter table table_name add columns(work string); 添加列名
alter table table_name replace columns(name string); 替换列名
内部表:
HDFS中为所属数据库目录下的子文件夹
数据完全由Hive管理,删除表(元数据)会删除数据
外部表:
数据保存在指定位置的HDFS路径中
Hive不完全管理数据,删除表(元数据)不会删除数据
静态分区(分区:提高查询性能)理解为文件夹
创建表时添加分区字段 patitioned by(column,xxx) 此coulmn 在表中不存在
alter table students add partition(sex=‘m’) partition(sex=‘f’);
show partitions table_name;
insert into students partition(sex=‘m’) select 1,‘zs’;
alter table employee_test drop partition(year=2019,month=7);
动态分区 (分区:提高查询性能)
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
insert into students partition(sex) select 1,‘zs’,‘m’ as sex;
分桶 (按照分桶字段的哈希值取模除以分桶的个数) 理解为文件
好处:1 方便取样 2 提高join查询效率
创建表 clustered by (dept) into 3 buckets 按字段分桶 此字段在表中存在
set hive.enforce.bucketing=true; //让hive强制分桶,自动按照分桶表的bucket 进行分桶。
添加数据自动分桶
基于桶的抽样:select * from table_name tablesmple(bucket 1 out of 3 on xx);
-------------------取样并不是一个精确的操作,因此这个 比例不一定要是桶数的整数倍---------------------
视图 相当于索引)创建视图create view view_name as select xxx ; 删除 drop view xxx;
create view vw_customer_details as
base64(binary(last_name)) as last_name ,
//select unbase64(base64(binary(store_name))) from ext_store_details base64解码
MD5(credit_no) as credit_no
from ext_customer_details
侧视图–lateral view 意义:配合explode ,一个语句生成把单行数据拆解成多行后的数据结果集 。
explode 作用是处理map结构的字段还有array字段也可以
SELECT explode(array(10,20));
select explode(map('A','Apple','O','Orange'));
行转列
select name,myscore from xx lateral view explode(split(score,’,’)) x as myscore;
select split(score,’,’) from xx;字符串分割为数组
列转行
select id,
max(if(course='a ',1,0))a,
max(if(course='b ',1,0))b,
max(if(course='c ',1,0))c,
max(if(course='d ',1,0))d,
max(if(course='e ',1,0))e,
max(if(course='f ',1,0))f
from t_course group by id;
hive常用函数:
select if(pmod(datediff(current_date, '1920-01-01') - 3, 7)='0',7,pmod(datediff(current_date, '1920-01-01') - 3, 7));
cast(xx as xx) 转换字段类型
coalesce 相当于mysql中 ifnull
==select nvl(null,1) 如果null是具体的数就返回具体的数。
insert into xx select name,coalesce(chinese,0),coalesce(math,0),coalesce(english,0) from sss
--------------------------------先更改配置文件---------------------创建内部事务分桶表----------------------------
插入操作------>更新操作
INPUT__FILE__NAME:Mapper Task的输入文件名称
BLOCK__OFFSET__INSIDE__FILE:当前全局文件位置
select b.userid,if(trantype=1,tranmoney,-tranmoney) from bankcards b;
select * from userinfos u where not exists(select b.userid from bankcards b )where u.userid=b.userid group by b.userid); 不存在也要内外关联 在hive中没有not in
insert overwrite table table_name select xxx; 加载数据
数据倾斜情况以及解决
数据倾斜:数据的分散度不够,数据集中在一台或者几台计算机上计算,计算时间远超过平均计算速度,导致整个计算过程过慢。
hive 中数据倾斜,一般都发生在sql中group和on上,而且数据逻辑绑定比较深。
解决思路:调节参数和调节sql语句
1.当遇到大小表关联时:
在hadoop中可以通过将小表加载到缓存 这种方式就是mapjoin方式
在hive中可以设置 mapjoin set hive.auto.convert.join=true 阈值25M
2.部分数据相对特别少
在mapreduce中 partition 部分自定义哈希
在hive中partition 自定义分区
3.当遇到很多小数据表时:
hive中带来很多的参数和机制来调节数据倾斜
set mapred.max.split.size=100000000;
set mapred.min.split.size=100000000;
set mapred.min.split.size.per.node=100000000;
set mapred.min.split.size.per.rack=100000000;
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
order by排序 对全局数据进行排序,只有一个reduce工作,速度慢
select * from offers order by case when offerid = 1 then 1 else 0 end;
sort by
sort by 只能保证对每个reduce里的字段有序。 可以指定reduce个数 set mapred.reduce.tasks=n 来指定,对输出的数据再执行归并排序。
distribute by
distribute by 类似于sql中的group by 确保具有匹配列值的行被分区到相同的reducer,不会对每个reducer的输出进行排序。是控制在map端如何拆分数据给reduce端的。hive会根据distribute by后面列,对应reduce的个数进行分发,默认是采用hash算法。
SELECT department_id , name, employee_id, evaluation_scoreFROM employee_hr DISTRIBUTE BY department_id SORT BY evaluation_score DESC;
cluster by
除了distribute by的功能外,还会对改字段进行排序,所以cluster by = distribute by +sort by 可以理解为分区在对指定字段排序
Hive 聚合
基础聚合 :
使用内置函数进行数据聚合 比如:max(distinct col)、avg(distinct col)等
select count(null) = 0
count(*) 所有值不全为NULL时,加1操作
count(1) 不管有没有值,只要有这条记录,值就加1
count(col) col列里面的值为null,值不会加1,这个列里面的值不为NULL,才加1
高级聚合
grouping sets 实现对同一数据集进行多重GROUP BY操作
SELECT a, b, SUM( c ) FROM tab1 GROUP BY a, b GROUPING SETS ( (a, b), a, b, ( ) )
GROUP BY WITH CUBE|ROLLUP
cube:对分组列进行所有可能组合的聚合
collect_set 和collect_list函数(数据进行关联聚合,多行多列转换为单行单列)
collect_set 和collect_list 函数的区别:set会去重
select 重复的多列字段,collect_set/list(需要被形成单列的字段) ps这边结果会为数组 from 表 group by 重复的多列字段 可通过下表如[0] 来获取数组的第几列值,若超出范围会为NULL
concat/concat_ws函数(按指定格式合并分组内全部记录)
直接用concat函数,concat后面的参数后面可以是多列,如果其中某一列为NULL,那么合并结果也为NULL
concat_ws 函数第一个参数为指定合并分隔符,后面的参数可以是多列,有NUll值无影响
select month,day,concat_ws(',',collect_list(cookieid)) cw from test2 group by month,day
explde函数 只能是数组或者map类型
对map字段进行explode 取别名要取两个as(a,b) 因为explode后会变成两列
直接在select 后面用explode使用时,不能加其他字段,不能嵌套,不能groupby/cluster by/sort by
为什么通常与lateral view一起出现?
select src.id, mytable.col1, mytable.col2 from src lateral view explode_map(properties) mytable(虚拟表名) as col1, col2(map字段的列别名);
split(str,‘分隔符’) 分割后形成数组
substr 和substring的用法一样,substring(string A,int start,int len)
窗口函数
在什么情况下使用?
用于分区排序,动态group By Top N 累计计算 层次查询
row_number 会生成一列连续的序号,rank()函数出现1 1 3 dense_rank()则出现1 1 2这样的序号
lag是迟滞的意思,也就是对某一列进行往后几行,lead是对某一列提前几行
求出每个页面访问量的top2
select username,dept,score, row_number() over() from userinfos order by dept,score
elect page,createtime,pv,
row_number() over(partition by page order by pv) as rn
where rn<3;
按层次查询,如一年中,统计出工资前1/4之的部门信息,使用NTILE分析函数,把所有工资分为4份,为1的哪一份就是我们想要的结果:
select deptid,sum(salary),ntile(4) over (order by sum(salary) desc nulls last) til_col from employee group by deptid;
注意:order by 时,desc NULL 值排在首位,ASC时NULL值排在末尾,可以通过NULLS LAST、NULLS FIRST 控制
分组后的数据标上序号。
select userid,username,dept,score,row_number() over(partition by dept order by score) from userinfos
计算累计和:统计1-12月的累积销量,即1月为1月份的值,2月为1-2月份值的和,3月为123月份的和,12月为1-12月份值的和
SELECT month,SUM(amount) month_amount, SUM( SUM(amount)) OVER (ORDER BY month ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENTROW) AS cumulative_amount FROM table_name GROUP BY month ORDER BY month;
注:SUM( SUM(amount)) 内部的SUM(amount)为需要累加的值,在上述可以换为 month_amount
计算前三个月之间的和
SUM( SUM(amount)) OVER (ORDER BY month 3 PRECENDING) AS cumulative_amount
在使用 row_number() over()函数时候,over()里头的分组以及排序的执行晚于 where group by order by 的执行。 如果没有分组hive随机分组而不是默认为1
行窗口和范围窗口
UDF函数
maven导入jar包-------------hive-common和 hive-exec 以及hadoop的common
继承UDF类 创建evaluate方法
public class SayHello extends UDF {
public String evaluate(String msg){
return "Hello,"+msg;
}
}
打成jar包 上传到hdfs
创建UDF函数 create [temporary] function [functino_name] as 'class_path' using jar 'hdfs:///xxx/xx.jar'
调用 select funcname("传参")
public class SearchArray extends GenericUDF {
//准备三个工具
private ListObjectInspector array;
private ObjectInspector singleEle;
private ObjectInspector second;
private IntWritable result=new IntWritable(-1);
/**
* 设置本函数的返回值类型
* @param
* @return
* @throws UDFArgumentException
*/
@Override
public ObjectInspector initialize(ObjectInspector[] args) throws UDFArgumentException {
//对第一个参数强转成集合
array =(ListObjectInspector) args[0];
//获得集合中单个元素
singleEle = array.getListElementObjectInspector();
//获得第二个参数
second = args[1];
return PrimitiveObjectInspectorFactory.writableIntObjectInspector;
}
@Override
public Object evaluate(DeferredObject[] args) throws HiveException {
this.result.set(-1);
Object arr = args[0].get();
Object val = args[1].get();
int len = array.getListLength(arr);
for (int i = 0; i < len; i++) {
Object ele= array.getListElement(arr,i);
if (ele!=null){
if (ObjectInspectorUtils.compare(val,second,ele,singleEle)==0){
this.result.set(1);
break;
}
}
}
return result;
}
//说明文件
@Override
public String getDisplayString(String[] strings) {
return null;
}
}