自己总结sql用法

**
一篇超级好的sql执行文档
https://www.cnblogs.com/cdf-opensource-007/p/6502556.html

- 2018/12/05 with as 用法

**

一、hivesql中(注意:mysql不支持),with as语句的作用是相当于创建了一个中间表,加载到内存中,这样在后续的使用中极大的提高速度(不用建表,insert数据到中间表;加载内存,使用数据速度快)。
二、使用
WITH t1 AS (
SELECT *
FROM carinfo
),
t2 AS (
SELECT *
FROM car_blacklist
)
SELECT *
FROM t1, t2

注意:这里必须要整体作为一条sql查询,即with as语句后不能加分号,不然会报错。

三、注意事项

  1. with子句必须在引用的select语句之前定义,同级with关键字只能使用一次,多个只能用逗号分割;最后一个with 子句与下面的查询之间不能有逗号,只通过右括号分割,with 子句的查询必须用括号括起来.

以下写法会报错:

with t1 as (select * from carinfo)
with t2 as (select * from car_blacklist)
select * from t1,t2
1
2
3
with t1 as (select * from carinfo);
select * from t1
1
2
2.如果定义了with子句,但其后没有跟select查询,则会报错!

以下写法会报错:

with t1 as (select * from carinfo)
1
正确写法(没有使用 t1没关系,其后有select就行):

with t1 as (select * from carinfo)
select * from carinfo
1
2
3.前面的with子句定义的查询在后面的with子句中可以使用。但是一个with子句内部不能嵌套with子句!

正确写法:

with t1 as (select * from carinfo),
t2 as (select t1.id from t1)
select * from t2

- 2018/12/13 使用group up代替distinct

近期我司大数据部门事故频发,distinct一张表的四万分区的表,zookeeper产生四万余lock,大数据部门查的是使用distinct,产生严重的数据倾斜。
Hive去重统计
相信使用Hive的人平时会经常用到去重统计之类的吧,但是好像平时很少关注这个去重的性能问题,但是当一个表的数据量非常大的时候,会发现一个简单的count(distinct order_no)这种语句跑的特别慢,和直接运行count(order_no)的时间差了很多,于是研究了一下。
先说结论:能使用group by代替distinc就不要使用distinct,例子:

实际论证
order_snap为订单的快照表 总记录条数763191489,即将近8亿条记录,总大小:108.877GB,存储的是公司所有的订单信息,表的字段大概有20个,其中订单号是没有重复的,所以在统计总共有多少订单号的时候去重不去重结果都一样,我们来看看:
统计所有的订单有多少条条数,一个count函数就可以搞定的sql性能如何。

DISTINCT
1
2
3
4
5
6
7
select count(distinct order_no) from order_snap;
Stage-Stage-1: Map: 396 Reduce: 1 Cumulative CPU: 7915.67 sec HDFS Read: 119072894175 HDFS Write: 10 SUCCESS
Total MapReduce CPU Time Spent: 0 days 2 hours 11 minutes 55 seconds 670 msec
OK
_c0
763191489
Time taken: 1818.864 seconds, Fetched: 1 row(s)
GROUP BY
1
2
3
4
5
6
7
8
select count(t.order_no) from (select order_no from order_snap group by order_no) t;
Stage-Stage-1: Map: 396 Reduce: 457 Cumulative CPU: 10056.7 sec HDFS Read: 119074266583 HDFS Write: 53469 SUCCESS
Stage-Stage-2: Map: 177 Reduce: 1 Cumulative CPU: 280.22 sec HDFS Read: 472596 HDFS Write: 10 SUCCESS
Total MapReduce CPU Time Spent: 0 days 2 hours 52 minutes 16 seconds 920 msec
OK
_c0
763191489
Time taken: 244.192 seconds, Fetched: 1 row(s)
结论:第二种写法的性能是第一种的7.448499541倍
注意到为什么会有这个差异,Hadoop其实就是处理大数据的,Hive并不怕数据有多大,怕的就是数据倾斜,我们看看两者的输出信息:

1
2
3
4

distinct

Stage-Stage-1: Map: 396 Reduce: 1 Cumulative CPU: 7915.67 sec HDFS Read: 119072894175 HDFS Write: 10 SUCCESS

group by

Stage-Stage-1: Map: 396 Reduce: 457 Cumulative CPU: 10056.7 sec HDFS Read: 119074266583 HDFS Write: 53469 SUCCESS
发现猫腻了没有,使用distinct会将所有的order_no都shuffle到一个reducer里面,这就是我们所说的数据倾斜,都倾斜到一个reducer这样性能能不低么?再看第二个,直接按订单号分组,起了457个reducer,将数据分布到多台机器上执行,时间当然快了.
由于没有手动指定Reduce的个数,Hive会根据数据的大小动态的指定Reduce大小,你也可以手动指定

hive> set mapred.reduce.tasks=100;

类似这样,所以如果数据量特别大的情况下,尽量不要使用distinct吧。
但是如果你想在一条语句里看总记录条数以及去重之后的记录条数,那没有办法过滤,所以你有两个选择,要么使用两个sql语句分别跑,然后union all或者就使用普通的distinct。具体来说得看具体情况,直接使用distinct可读性好,数据量如果不大的话推荐使用,如果数据太大了,性能受到影响了,再考虑优化

-2018/12/14 join的用法(相比union他是横向扩展,union 是纵向做加法,也就是说join后的展示是多了列,union是多了行)

有时为了得到完整的结果,我们需要从两个或更多的表中获取结果。我们就需要执行 join。
join(也就是inner join)
写法:
SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons, Orders
WHERE Persons.Id_P = Orders.Id_P
或者
SELECT Persons.LastName, Persons.FirstName, Orders.OrderNo
FROM Persons
INNER JOIN Orders
ON Persons.Id_P = Orders.Id_P
ORDER BY Persons.LastName

除了我们在上面的例子中使用的 INNER JOIN(内连接),我们还可以使用其他几种连接。

下面列出了您可以使用的 JOIN 类型,以及它们之间的差异。

JOIN: 如果表中有至少一个匹配,则返回行
LEFT JOIN: 即使右表中没有匹配,也从左表返回所有的行
RIGHT JOIN: 即使左表中没有匹配,也从右表返回所有的行
FULL JOIN: 只要其中一个表中存在匹配,就返回行

不管是什么join只要不写on或者on的条件出问题,比如都是null会导致产生笛卡儿积,产生爆炸数据量。

-2018/12/14 union和union all用法

SQL UNION 操作符
UNION 操作符用于合并两个或多个 SELECT 语句的结果集。

请注意,UNION 内部的 SELECT 语句必须拥有相同数量的列。列也必须拥有相似的数据类型。同时,每条 SELECT 语句中的列的顺序必须相同。

SQL UNION 语法
SELECT column_name(s) FROM table_name1
UNION
SELECT column_name(s) FROM table_name2
注释:默认地,UNION 操作符选取不同的值。如果允许重复的值,请使用 UNION ALL。

SQL UNION ALL 语法
SELECT column_name(s) FROM table_name1
UNION ALL
SELECT column_name(s) FROM table_name2
另外,UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。

2019\3\7 case when 用法

例如 http://www.cnblogs.com/qingyunzong/p/8747656.html 中,第二个案例。
涉及到纵向比较的时候,先行转列,横向比较比较简单。设计case when 的用法,是每一行开始遍历 case XXX when XXX 生成一行,一个学号有几个课程就有几行,再用group By 加 sid max(shuxue),max(yuwen) 合成一行 ,再作对比!!

2019\3\7 行转列不止只有case when ,还可用collect_set ()[] 和 collect_list()[] 和explode()用法

https://www.cnblogs.com/cc11001100/p/9043946.html

collect_list()不去重,collect_set() 去重,他们一般会配合group
By 函数 【】 表示这个数组的第几位

https://www.cnblogs.com/linehrr-freehacker/p/3309088.html
explode()将数组转成列

2019\3\8 Hive几种排序的特点

   1.order by 全局排序

   2.sort by  非全局排序

   3.distribute by hash散列分区,常和sort by同时使用。即分区又排序,需要设置mapreduce.job.reduces的个数

   4.cluster by 当distribute by 和sort by的字段相同时,等同于cluster by.可以看做特殊的distribute + sort

2019\3\8 Multi-group by 是hive的一个非常好的特性,请举例说明

from A
insert overwrite table B
select A.a, count(distinct A.b) group by A.a
insert overwrite table C
select A.c, count(distinct A.b) group by A.c

2019\3\8 行转列:

LATERAL VIEW的使用:
侧视图的意义是配合explode(或者其他的UDTF),一个语句生成把单行数据拆解成多行后的数据结果集。

语法:
select mobile_no,lala,wawa from credit.aa
lateral view explode(split(first_bill_date,’-’)) goods as lala
lateral view explode(split(created_at,’:’))kk as wawa;

lateral view explode(split(created_at,’:’))kk lateral view explode(split(created_at,’:’)) 相当于一个虚拟表,kk相当于这个虚拟表的表名 ,通过虚拟表与原表credit.aa笛卡尔积得到我们想要的表)

98997229723 2017 2016-05-28 20
98997229723 2017 52
98997229723 2017 06
98997229723 05 2016-05-28 20
98997229723 05 52
98997229723 05 06
98997229723 01 2016-05-28 20
98997229723 01 52
98997229723 01 06

因为

只是使用explode的话,要使用mobile的话就不行了
hive> select mobile_no, explode(split(first_bill_date,’-’)) from credit.aa ;
FAILED: SemanticException [Error 10081]: UDTF’s are not supported outside the SELECT clause, nor nested in expressions

只能

hive> select explode(split(first_bill_date,’-’)) from credit.aa ;
Query ID = bdpms_20190308144343_868a2a86-6b8f-45c5-87b9-79ea92c4730e
Total jobs = 1
Launching Job 1 out of 1
In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=
In order to limit the maximum number of reducers:
set hive.exec.reducers.max=
In order to set a constant number of reducers:
set mapreduce.job.reduces=
。。。。。

2019\3\11 hql的 over():

over()必须和分析函数一块使用 ,比如row_number() 、sum() …

猜你喜欢

转载自blog.csdn.net/SmartShylyBoy/article/details/84819585