06_Hive分桶机制及其作用
1.Clustered By
对于每一个表(table)或者分区, Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。
Hive也是针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在
哪个桶当中。
把表(或者分区)组织成桶(Bucket)有两个理由:
(1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体
而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的
实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同
列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
(2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一
小部分数据上试运行查询,会带来很多方便。
2.分桶
分桶是相对分区进行更细粒度的划分,它是相当于MapReduce中的分区,分桶将整个数据按照某列属性值的hash
值进行区分,例如如果根据id属性分为3个桶,就是对id属性值的hash值对3取摸,按照取模结果对数据分桶。如取
模结果为0的数据记录存放到一个文件,取模为1的数据存放到一个文件,取模为2的数据存放到一个文件
1.创建带桶的表:导入的数据已经是被分好桶和排好序的
在分桶之前要执行命令:set hive.enforce.bucketing = true; set mapreduce.job.reduces=4;从而设置分桶
为true,并且reduce数量是分桶的数量个数;
关键字clustered by 指定分区依据的列名;
与分区不同的是,分区依据的不是真实数据表文件中的列,而是我们指定的伪列,但是分桶是依据数据表中真实
的列而不是伪列。所以在指定分区依据的列的时候要指定列的类型,因为在数据表文件中不存在这个列,相当于新建
一个列。而分桶依据的是表中已经存在的列,这个列的数据类型显然是已知的,所以不需要指定列的类型
如上只是说明了表会分桶,具体的分区需要在插入数据时产生。最好的插入数据方式是insert into table;
2.带桶的表中插入select数据(Cluster by(id)):表示根据id分桶并排序
cluster by和sort by不能放在一起查询
按照上面的分桶结果会在表目录下产生多个文件:/user/hive/warehouse/test_db/t_buk/
查看文件信息:
3.带桶的表中插入select数据(distribute by (id) sort by (id)):
按照上面的分桶结果会在表目录下产生多个文件:/user/hive/warehouse/test_db/t_buk/
如上的的sql查询语句实际上是根据id作为key进行key.hashcode%4产生四个区,即就是用distribute by (id)
来指定分区字段,使用sort by (id)指定排序字段
总结:
因此,如果分桶和sort字段是同一个时,此时,cluster by = distribute by + sort by
如果将reduce数量设置为4,使用select * from t_test order by name;就会强制将reduce设置为1,会得到全局结果;
SELECT语法操作: 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 分桶表的作用:最大的作用是用来提高join操作的效率; (思考这个问题:select a.id,a.name,b.addr from a join b on a.id = b.id; 如果a表和b表已经是分桶表,而且分桶的字段是id字段,那么做这个操作的时候就不需要再进行全表笛卡尔积了。但是如果标注了分桶但是实际上数据并没有分桶,那么结果就会出问题。