• Hive之分区(Partitions)和桶(Buckets)


    转自:http://www.aahyhaa.com/archives/316

    hive引入partition和bucket的概念,中文翻译分别为分区和桶(我觉的不是很合适,但是网上基本都是这么翻译,暂时用这个吧),这两个概念都是把数据划分成块,分区是粗粒度的划分桶是细粒度的划分,这样做为了可以让查询发生在小范围的数据上以提高效率。

    首先介绍分区的概念,还是先来个例子看下如果创建分区表:
    [code lang=”sql”]
    create table logs_partition(ts bigint,line string) –ts timestamp line 每一行日志
    partitioned by (dt string,country string) — 分区列 dt 日志产生日期
    [/code]
    创建分区表需要在定义表的时候声明分区列,这个分区列是个比较有意思的东西下面来看看,向表中导入数据:
    [code lang=”sql”]
    load data local inpath ‘input/hive/partitions/file1′
    into table logs_partition
    partition(dt=’2001-01-01′,country=’GB’);
    …….
    — 看下表的结构
    hive> desc logs_partition;
    OK
    ts bigint None
    line string None
    dt string None
    country string None

    # Partition Information
    # col_name data_type comment

    dt string None
    country string None
    Time taken: 0.265 seconds, Fetched: 10 row(s)

    查看一个表的所有分区
    hive> show partitions logs_partition;
    OK
    dt=2001-01-01/country=GB
    dt=2001-01-01/country=US
    dt=2001-01-02/country=GB
    dt=2001-01-02/country=US
    Time taken: 0.186 seconds, Fetched: 4 row(s)

    [/code]
    导入完数据后看下hive数据仓库表logs_partition下的文件目录结构
    /user/hive/warehouse/logs_partition
    Screenshot from 2013-10-10 17:46:25
    看到了吧分区列都成了目录了,这样查询的时候就会定位到某个目录下而大大提高了查询效率,在查看表结构的时候分区列跟其他列并无区别,看个查询语句:
    [code lang=”sql”]
    SELECT ts, dt, line
    FROM logs
    WHERE country=’GB’;

    1 2001-01-01 Log line 1
    2 2001-01-01 Log line 2
    4 2001-01-02 Log line 4
    Time taken: 36.316 seconds, Fetched: 3 row(s)

    [/code]
    这个查询只会查询file1, file2, file4这三个文件还有一个有趣的问题就是,查看下数据文件fieldX
    里面都只包含两列ts和line并不包含dt和country这两个分区列,但是从查询结果看分区列和非分区列并无差别,实际上分区列都是从数据仓库的分区目录名得来的。

    接下来说说桶,桶是更为细粒度的数据范围划分,它能使一些特定的查询效率更高,比如对于具有相同的桶划分并且jion的列刚好就是在桶里的连接查询,还有就是示例数据,对于一个庞大的数据集我们经常需要拿出来一小部分作为样例,然后在样例上验证我们的查询,优化我们的程序。

    下面看看如何创建带桶的表
    [code lang=”sql”]
    create table bucket_user (id int,name string)
    clustered by (id) into 4 buckets;
    [/code]
    关键字clustered声明划分桶的列和桶的个数,这里以用户的id来划分桶,划分4个桶。
    以下为了简便划分桶的列简称为桶列
    hive会计算桶列的hash值再以桶的个数取模来计算某条记录属于那个桶

    向这种带桶的表里面导入数据有两种方式,一种是外部生成的数据导入到桶表,一种是利用hive来帮助你生成桶表数据
    由于hive在load数据的时候不能检查数据文件的格式与桶的定义是否匹配,如果不匹配在查询的时候就会报错,所以最好还是让hive来帮你生成数据,简单来说就是利用现有的表的数据导入到新定义的带有桶的表中,下面来看看:
    已经存在的表:
    [code lang=”bash”]
    hive> select * from users;
    OK
    0 Nat
    2 Joe
    3 Kay
    4 Ann

    hive> set hive.enforce.bucketing=true –必须设置这个数据,hive才会按照你设置的桶的个数去生成数据
    [/code]

    下面把user的数据导入到bucketed_users中
    [code language=”lang='sql”]
    insert overwrite table bucketed-users
    select * from users;
    [/code]
    然后见证奇迹的时刻:
    [code lang=”bash”]
    hive> dfs -ls /user/hive/warehouse/bucketed_users;
    -rw-r–r– 1 root supergroup 12 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000000_0
    -rw-r–r– 1 root supergroup 0 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000001_0
    -rw-r–r– 1 root supergroup 6 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000002_0
    -rw-r–r– 1 root supergroup 6 2013-10-10 18:48 /user/hive/warehouse/bucketed_users/000003_0

    hive> dfs -cat /user/hive/warehouse/bucketed_users/000000_0;
    0Nat
    4Ann

    [/code]

    下面来看看利用bucket来对示例数据进行查询
    [code lang=”sql”]
    —带桶的表
    select * from bucketed_users
    tablesample(bucket 1 out of 4 on id);

    —不带桶的表
    select * from users
    tablesample(bucket 1 out of 4 on rand());

    [/code]
    tablesample的作用就是让查询发生在一部分桶上而不是整个数据集上,上面就是查询4个桶里面第一个桶的数据
    相对与不带桶的表这无疑是效率很高的,因为同样都是需要一小部分数据,但是不带桶的表需要使用rand()函数,需要在整个数据集上检索。

  • 相关阅读:
    JS练习:定时器--背景颜色交替变换
    JS练习:切换图片
    BOM对象和DOM对象
    CSS练习:仿小米官网
    classification
    where does the error come from
    梯度下降
    torch 中各种图像格式转化
    regression
    torch 的包应用
  • 原文地址:https://www.cnblogs.com/cxzdy/p/5524477.html
Copyright © 2020-2023  润新知