美文网首页
Hive分桶之BUCKET详解

Hive分桶之BUCKET详解

作者: 丹之 | 来源:发表于2018-12-19 10:28 被阅读13次

    Bucket

    1.对于每一个表(table)或者分区(partition), Hive可以进一步组织成桶,也就是说桶是更为细粒度的数据范围划分。Hive也是 针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。

    2,把表(或者分区)组织成桶(Bucket)有两个理由:
    *(1)获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
    *(2)使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。
    下面来一个例子:

    Create table dz_test(
        id  bigint  comment’编号’,(ps:comment为注释)
        name string comment’姓名’
    )comment’编号与姓名表’
    Partitioned by(pdate string)
    Clustered by(id)     按id分桶,自动哈希分桶
    Sorted by(id)   按id排序
    Into 4 buckets   分成4个桶
    Row format delimited 设置创建的表在加载数据的时候,支持的列分隔符
    Fields terminated by ‘\t’  每个字段按\t分割
    Lines terminated by’\n’ stored as textfile; 按\n为断行符,指定导入的文件为纯文本。
    //Hive本身支持的文件格式只有:Text File,Sequence File,如果数据需要压缩,使用 //[STORED AS SEQUENCE]
    

    下面load数据:
    插入数据之前需要设置参数hive.enforce.bucketing=true,以强制hive的reducer数目为分桶数。如果不设置这个hive参数,最后的桶个数可能不是建表语句中的个数。另外,也可以通过将参数mapred.reduce.tasks设置为桶的数目来控制reducer的数目,建议采用第一种方式。

    Set hive.enforce.bucketing=true;
    Load data local inpath’/home/Hadoop/….’ overwrite into table dz_test partition(pdate=‘2015-10’)
    

    物理上,每个桶就是表(或分区)目录里的一个文件。它的文件名并不重要,但是桶 n 是按照字典序排列的第 n 个文件。事实上,桶对应于 MapReduce 的输出文件分区:一个作业产生的桶(输出文件)和reduce任务个数相同。

    我们可以通过查看刚才 创建的bucketd_users表的布局来了解这一情况。运行如下命令:

    查看表的结构:
    hive> dfs -ls /user/hive/warehouse/dz_test; 
    将显示有4个新建的文件。文件名如下(文件名包含时间戳,由Hive产生,因此 每次运行都会改变): 
    attempt_201701221636_0016_r_000000_0 
    attempt_201701221636_0016_r-000001_0 
    attempt_201701221636_0016_r_000002_0 
    attempt_201701221636_0016_r_000003_0 
    第一个桶里包括用户ID和4,因为一个INT的哈希值就是这个整数本身,在这里 除以桶数(4)以后的余数:2
    读取数据,看每一个文件的数据:
    hive> dfs -cat /user/hive/warehouse/dz_test/*0_0; 
    0 Nat 
    4 Ann 
    用TABLESAMPLE子句对表进行取样,我们可以获得相同的结果。这个子句会将 查询限定在表的一部分桶内,而不是使用整个表:
    . 对桶中的数据进行采样:
    hive> SELECT * FROM dz_test 
    >TABLESAMPLE(BUCKET 1 OUT OF 4 ON id); 
    0 Nat 
    4 Ann 
    桶的个数从1开始计数。因此,前面的查询从4个桶的第一个中获取所有的用户。 对于一个大规模的、均匀分布的数据集,这会返回表中约四分之一的数据行。我们 也可以用其他比例对若干个桶进行取样(因为取样并不是一个精确的操作,因此这个 比例不一定要是桶数的整数倍)。例如,下面的查询返回一半的桶:
    7. 查询一半返回的桶数:
    hive> SELECT * FROM dz_test 
    >    TABLESAMPLE(BUCKET 1 OUT OF 2 ON id); 
    0 Nat 
    4 Ann 
    2 Joe 
    因为查询只需要读取和TABLESAMPLE子句匹配的桶,所以取样分桶表是非常高效 的操作。如果使用rand()函数对没有划分成桶的表进行取样,即使只需要读取很 小一部分样本,也要扫描整个输入数据集: 
    hive〉 SELECT * FROM dz_test 
    > TABLESAMPLE(BUCKET 1 OUT OF 4 ON rand()); 
    2 Doe 
    ①从Hive 0.6.0开始,对以前的版本,必须把mapred.reduce .tasks设为表中要填 充的桶的个数。如果桶是排序的,还需要把hive.enforce.sorting设为true。 
    ②显式原始文件时,因为分隔字符是一个不能打印的控制字符,因此字段都挤在一起。 
    
    

    https://blog.csdn.net/m0_37534613/article/details/55258928

    总结:在Join两边的时候使用到view,这样可以使用分桶的概念,优化Join的性能。

    相关文章

      网友评论

          本文标题:Hive分桶之BUCKET详解

          本文链接:https://www.haomeiwen.com/subject/dzueaftx.html