本文主要根据一些具体SQL实例来介绍说明cluster by、distribute by + sort by和order by的区别。同时通过实例说明create table指定clustered by 和sort by。
create table table(c1 int,c2 int,c3 int);
insert into table dual select 1,2,3 from (select count(*) from dual)a;
insert into table dual select 1, 3, 4 from (select count(*) from dual)a;
insert into table dual select 1, 1, 5 from (select count(*) from dual)a;
insert into table dual select 1, 2, 2 from (select count(*) from dual)a;
insert into table dual select 1, 1, 2 from (select count(*) from dual)a;
hive> select * from dual;
OK
1 2 3
1 3 4
1 1 5
1 2 2
1 1 2
Time taken: 0.105 seconds, Fetched: 5 row(s)
create table t1_cluster (c1 int,c2 int,c3 int) clustered by (c2) sorted by (c3) into 2 buckets;
insert overwrite table t1_cluster select * from dual;
hive> select * from t1_cluster;
OK
1 2 2
1 2 3
1 1 2
1 3 4
1 1 5
Time taken: 0.111 seconds, Fetched: 5 row(s)
上面的脚本主要是为了构建数据,其中dual表数据可以认为是源表数据,而t1_clsuter表数据则是clustered by c2 并且sort by c3,同时写入2个buckets。
首先设置reduce个数为2,为了可以更加清晰地看到数据分布。
set mapred.reduce.tasks=2;
hive> select * from t1_cluster cluster by c2;
OK
--bucket0
1 2 3
1 2 2
--bucket1
1 1 5
1 1 2
1 3 4
Time taken: 1.768 seconds, Fetched: 5 row(s)
从结果里面可以看到,如果SQL指定cluster by c2,则数据基于c2分布,且按照升序排序。
hive> select * from t1_cluster distribute by c2;
OK
--bucket0
1 2 3
1 2 2
--bucket1
1 1 5
1 3 4
1 1 2
Time taken: 1.77 seconds, Fetched: 5 row(s)
从结果可以看到,数据是基于c2分布,但并没有按照c2升序或者降序排序。
这里也清晰看到cluster by和distribute by的区别在于都是基于key分布,前者会按照key升序排序,而后者不会排序。
hive> select * from t1_cluster distribute by c2 sort by c3;
OK
--bucket0
1 2 2
1 2 3
--bucket1
1 1 2
1 3 4
1 1 5
Time taken: 1.69 seconds, Fetched: 5 row(s)
从结果可以清晰看到,数据基于c2分布,但同时基于c3升序排序。
下面同时对比下sort by添加c2列。
hive> select * from t1_cluster distribute by c2 sort by c2,c3;
OK
--bucket0
1 2 2
1 2 3
--bucket1
1 1 2
1 1 5
1 3 4
Time taken: 1.767 seconds, Fetched: 5 row(s)
从结果来看,与sort by c2不同的是,这条SQL返回的结果不仅基于c2分布,同时还是基于c2,c3有序。
这里再添加一个例子。
hive> select * from t1_cluster distribute by c2 sort by c2;
OK
--bucket0
1 2 3
1 2 2
--bucket1
1 1 5
1 1 2
1 3 4
Time taken: 1.728 seconds, Fetched: 5 row(s)
这里主要是为了说明,cluster by c2与distribute by c2 sort by c2返回的结果其实是一致的,也即两者写法其实是等价。
hive> select * from t1_cluster order by c2;
OK
1 1 5
1 1 2
1 2 3
1 2 2
1 3 4
Time taken: 1.757 seconds, Fetched: 5 row(s)
查询语句order by c2结果是所有数据基于c2有序,也就是说order by是对整个数据集进行排序。
cluster by key是根据key对数据进行分布,并且在每个bucket里面根据key进行排序。而distribute by key仅仅是根据key对数据进行分布,如果同时添加sort
by子句,则会保证每个bucket数据是根据sort by的key有序。同时如果distribute by和sort by的key是相同情况下,则等价于cluster by子句。即cluster by kes <==>distribute by keys sort by keys。而order by则是对整个数据进行排序,没有任何分布概念。
最开始表的创建SQL可以看到t1_cluster表创建其实是cluster by c2然后sort by c3。然后查看所有数据。
hive> select * from t1_cluster;
OK
--bucket0
1 2 2
1 2 3
--bucket1
1 1 2
1 3 4
1 1 5
Time taken: 0.105 seconds, Fetched: 5 row(s)
首先t1_cluster创建了2个buckets,所以值2分布在bucket0号,而1分布在bucket1(取模)。发现对于bucket1的所有值,c2并没有排序,而对于c3列每个bucket都是基于c3有序。
所以create table的clustered by其实仅仅是分布,与Select语句中的cluster by其实并不一样。而是和Select语句中的distribute by相同。所以create table的clustered by sorted by其实等价于select的distribute by sort by。