Hive系列之分区表和桶

作者: wujustin | 来源:发表于2016-07-22 15:44 被阅读2668次

    为提升hive数据的查询和写入性能, hive提供了分区表机制。hive每个表格可以指定多个分区key, 这些分区key决定数据的存储方式,比如表格T有个日期型分区列ds, 表格的数据会存储在:表在hdfs路径/ds=<date>目录下,查询语句中ds='2008-09-01'类似过滤条件,可以直接查询表在hdfs路径/ds=<date>目录下数据, 达到提升性能的目的。
    hive提供两种分区表:静态分区和动态分区。两者主要的差别在于:加载数据的时候,动态分区不需要指定分区key的值, 会根据key对应列的值自动分区写入,如果该列值对应的分区目录还没有创建, 会自动创建并写入数据。下面实践演示:

    1.静态分区
    创建分区表

    hive >create table teacher(id INT, name string, tno string)
    partitioned by (work_date string)
    clustered by (id) sorted by (name) into 2 buckets
    row format delimited fields terminated by ',' stored as textfile;

    静态分区加载数据

    hive>load data local inpath '/home/warehouse/user.txt' overwrite into table teacher partition(work_date="2016-07-12");

    其中user.txt内容:
    1, t1, 01
    2, t2, 02
    3, t3, 03
    4, t4, 04

    分区创建完成后查看hdfs目录

    hive>dfs -ls /user/hive/warehouse/crwal_db.db/teacher/
    drwxrwxrwx - warehouse supergroup 0 2016-07-12 09:03 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-07-12

    可以看出创建的分区目录

    2.动态分区

    首先需要设置参数: 动态分区相关参数设置如下

    set hive.exec.dynamic.partition=true;(可通过这个语句查看:set hive.exec.dynamic.partition;)
    set hive.exec.dynamic.partition.mode=nonstrict; (strict要求至少有一个静态分区, nonstrict可以都是动态分区)
    set hive.exec.max.dynamic.partitions=100000;(如果自动分区数大于这个参数,将会报错)
    set hive.exec.max.dynamic.partitions.pernode=100000;

    创建一个临时表格, 用于加载数据, 然后把临时表格的数据插入到分区表。

    hive>create table tmp (
    id int, name string, tno string, work_date string)
    row format delimited fields terminated by ',' stored as textfile;

    本地文件数据

    $ cat user1.txt
    1,root,01,2016-07-11
    2,sys,02,2016-07-11
    3,user01,03,2016-07-11
    4,user02,04,2016-07-11
    5,user03,05,2016-07-11
    6,user04,06,2016-06-11
    7,user05,07,2016-06-11
    8,user06,08,2016-06-11
    9,user07,09,2016-06-11
    10,user08,10,2016-05-11
    11,user09,11,2016-05-11
    12,user10,12,2016-05-11

    加载数据到临时表

    load data local inpath "/home/warehouse/user1.txt" overwrite into table tmp;

    从临时表加载数据到分区表

    hive>insert into table teacher partition(work_date) select id, name, tno, work_date from tmp;

    再次查看hdfs中数据分区

    hive>dfs -ls /user/hive/warehouse/crwal_db.db/teacher/
    drwxrwxrwx - warehouse supergroup 0 2016-07-12 16:43 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-05-11
    drwxrwxrwx - warehouse supergroup 0 2016-07-12 16:43 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-06-11
    drwxrwxrwx - warehouse supergroup 0 2016-07-12 16:43 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-07-11

    上面的临时表work_date包括三个数据:2016-05-11, 2016-06-11, 2016-07-11,插入到以workdate为分区key的teacher表时, 会自动识别出这三种值,分别创建三个目录。而不需要像静态分区一样每插入一个分区key的数据都要一条如下插入语句:

    insert into table teacher partition(work_date="2016-05-11") select id, name, tno, work_date from tmp where work_date="2016-05-11";

    需要注意的是:

    在一个表同时使用动态和静态分区表时, 静态分区值必须在动态分区值的前面。
    选择分区key时,要防止数据倾斜, 数据严重分布不均衡。
    使用动态分区, 作为分区列的值要可以预测和枚举, 不能目录过多而每个目录数据又很少,会严重影响性能。

    3.桶
    对于每一个表(table)或者分区,Hive可以进一步组织成桶。Hive也是针对某一列进行桶的组织。Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。采用桶好处有两个:

    1. 数据sampling2. 提升某些查询操作效率,例如mapside join
      JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。

    hive >create table teacher(id INT, name string, tno string)
    partitioned by (work_date string)
    clustered by (id) sorted by (name) into 2 buckets
    row format delimited fields terminated by ',' stored as textfile;

    hive中table可以拆分成partition,table和partition可以通过‘CLUSTERED BY ’进一步分bucket,bucket中的数据可以通过‘SORT BY’排序。如上语句所示, 通过id列把数据分成2个桶, 桶中数据通过name排序。

    可以看下分区表里面分成桶以后的文件存储格式:

    hive>dfs -ls /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-06-11;
    -rwxrwxrwx 3 warehouse supergroup 24 2016-07-12 16:43 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-06-11/000000_0
    -rwxrwxrwx 3 warehouse supergroup 24 2016-07-12 16:43 /user/hive/warehouse/crawl_db.db/teacher/work_date=2016-06-11/000001_0

    可见每个分区数据被划分到了两个桶里面。

    下面看下桶在数据采样里面的应用:
    tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y)

    select * from teacher tablesample(bucket 1 out of 2 on id);

    相关文章

      网友评论

        本文标题:Hive系列之分区表和桶

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