谈笑间学会大数据-Hive中的分桶表

谈笑间学会大数据-Hive中的分桶表

你可以不够优秀,但是不要甘于平凡

Hive中的分桶表

官方文档

首先我们可以参考下官方文档,对于创建分桶表的一些描述

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-BucketedSortedTables

什么是分桶表?

​ 分桶是相对分区进行更细粒度的划分。分桶将整个数据内容安装某列属性值得hash值进行区分,如要安装name属性分为3个桶,就是对name属性值的hash值对3取摸,按照取模结果对数据分桶。如取模结果为0的数据记录存放到一个文件,取模为1的数据存放到一个文件,取模为2的数据存放到一个文件。桶是比表或分区更为细粒度的数据范围划分。针对某一列进行桶的组织,对列值哈希,然后除以桶的个数求余,决定将该条记录存放到哪个桶中。

语法

DDL语法
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]
分桶表语法
CREATE TABLE page_view(viewTime INT, userid BIGINT,
     page_url STRING, referrer_url STRING,
     ip STRING COMMENT 'IP Address of the User')
 COMMENT 'This is the page view table'
 PARTITIONED BY(dt STRING, country STRING)
 CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS
 ROW FORMAT DELIMITED
   FIELDS TERMINATED BY '\001'
   COLLECTION ITEMS TERMINATED BY '\002'
   MAP KEYS TERMINATED BY '\003'
 STORED AS SEQUENCEFILE;

In the example above, the page_view table is bucketed (clustered by) userid and within each bucket the data is sorted in increasing order of viewTime. Such an organization allows the user to do efficient sampling on the clustered column - in this case userid. The sorting property allows internal operators to take advantage of the better-known data structure while evaluating queries, also increasing efficiency. MAP KEYS and COLLECTION ITEMS keywords can be used if any of the columns are lists or maps.

The CLUSTERED BY and SORTED BY creation commands do not affect how data is inserted into a table – only how it is read. This means that users must be careful to insert data correctly by specifying the number of reducers to be equal to the number of buckets, and using CLUSTER BY and SORT BY commands in their query.

There is also an example of creating and populating bucketed tables.

分桶表的操作使用
  • 先创建分桶表,通过直接导入数据文件的方式

    数据准备 student.txt

    1001 ss1
    1002 ss2 
    1003 ss3 
    1004 ss4 
    1005 ss5 
    1006 ss6 
    1007 ss7 
    1008 ss8 
    1009 ss9 
    1010 ss10 
    1011 ss11 
    1012 ss12 
    1013 ss13 
    1014 ss14 
    1015 ss15 
    1016 ss16
    
  • 创建分桶表

    create table stu_buck(id int, name string) 
    clustered by(id) 
    into 4 buckets 
    row format delimited fields terminated by '\t'; 
    
  • 查看表结构

    hive (default)> desc formatted stu_buck; 
    Num Buckets: 4 
    
  • 导入数据到分桶表中

    hive (default)> load data local inpath '/datas/student.txt' into table stu_buck; 
    
  • 查看创建的分桶表中是否分成 4 个桶,发现并没有分成 4 个桶。是什么原因呢?

直接load data不会有分桶的效果,这样和不分桶一样,在HDFS上只有一个文件。

另一种方法试试呢?

  • 创建分桶表时,数据通过子查询的方式导入

    • 先建一个普通的 stu 表
    create table stu(id int, name string) 
    row format delimited fields terminated by '\t'; 
    
  • 向普通的 stu 表中导入数据

    load data local inpath '/datas/student.txt' into table stu; 
    
  • 清空 stu_buck 表中数据

    truncate table stu_buck; 
    select * from stu_buck; 
    
  • 导入数据到分桶表,通过子查询的方式

    insert into table stu_buck 
    select id, name from stu; 
    

    发现还是只有一个分桶。为什么尼?

    其实在官网上面已经有所描述了需要配置一个参数才可以de

    ​ https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL+BucketedTables

    需要设置一个属性

    hive (default)> set hive.enforce.bucketing=true; 
    hive (default)> insert into table stu_buck 
    select id, name from stu; 
    
  • 查询分桶的数据

    hive (default)> select * from stu_buck; 
    OK
    stu_buck.id stu_buck.name 
    1004 ss4 
    1008 ss8 
    1012 ss12 
    1016 ss16 
    1001 ss1 
    1005 ss5 
    1009 ss9 
    1013 ss13 
    1002 ss2 
    1006 ss6 
    1010 ss10 
    1014 ss14 
    1003 ss3 
    1007 ss7 
    1011 ss11 
    1015 ss15
    
  • 分桶抽样查询

对于非常大的数据集,有时用户需要使用的是一个具有代表性的查询结果而不是全部结果。Hive 可以通过对表进行抽样来满足这个需求。

查询表 stu_buck 中的数据。

hive (default)> select * from stu_buck tablesample(bucket 1 out of 4 on id); 

注:tablesample 是抽样语句,语法: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 的数据。 x 表示从哪个 bucket 开始抽取,如果需要取多个分区,以后的分区号为当前分区号加上 y。

例如,table 总 bucket 数为 4,tablesample(bucket 1 out of 2),表示总共抽取(4/2=)2 个 bucket 的数据,抽取第 1(x)个和第 4(x+y)个 bucket 的数据。

注意:x 的值必须小于等于 y 的值,否则会报错。报错信息如下:

FAILED: SemanticException [Error 10061]: Numerator should not be bigger than denominator in sample clause for table stu_buck

场景

抽样查询

对于非常大的数据集,用户不需要全部查询的结果,只需要一个代表性的查询结果时,可以通过对表进行分桶抽样。

每个桶内的数据是排序的,这样每个桶进行连接时就变成了高效的归并排序

数据分片

能够有效的根据某一个key,将数据进行分片,方便数据存储和计算

分区表 && 分桶表

分桶针对的是数据文件,分区针对的是数据目录而非文件

分区提供一个隔离数据和优化查询的便利方式。不过,并非所有的数据集都可形成合理的分区,特别是要确定分区合适的划分大小。

分桶是将数据集分解成更容易管理的若干部分的另一个技术。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章