zoukankan      html  css  js  c++  java
  • hive的分区

    https://www.cnblogs.com/yongjian/p/6640951.html

    Hive分区的概念与传统关系型数据库分区不同。

    传统数据库的分区方式:就oracle而言,分区独立存在于段里,里面存储真实的数据,在数据进行插入的时候自动分配分区。

    Hive的分区方式:由于Hive实际是存储在HDFS上的抽象,Hive的一个分区名对应一个目录名,子分区名就是子目录名,并不是一个实际字段。

    所以可以这样理解,当我们在插入数据的时候指定分区,其实就是新建一个目录或者子目录,或者在原有的目录上添加数据文件。

    Hive分区的创建

    Hive分区是在创建表的时候用Partitioned by 关键字定义的,但要注意,Partitioned by子句中定义的列是表中正式的列,但是Hive下的数据文件中并不包含这些列,因为它们是目录名。

    静态分区

    创建一张静态分区表par_tab,单个分区

    create table par_tab (name string,nation string) partitioned by (sex string) row format delimited fields terminated by ',';

    这时候通过desc查看的表结构如下

    复制代码
    hive> desc par_tab;
    OK
    name                    string                                      
    nation                  string                                      
    sex                     string                                      
              
    # Partition Information          
    # col_name                data_type               comment             
              
    sex                     string                                      
    Time taken: 0.038 seconds, Fetched: 8 row(s)
    复制代码

    准备本地数据文件par_tab.txt,内容 “名字/国籍”,将以性别(sex)作为分区

    jan,china
    mary,america
    lilei,china
    heyong,china
    yiku,japan
    emoji,japan

    把数据插入到表(其实load操作相当于把文件移动到HDFS的Hive目录下)

    load data local inpath '/home/hadoop/files/par_tab.txt' into table par_tab partition (sex='man');

    这时候在hive下查询par_tab表,变成了3列,注意。

    复制代码
    hive> select * from par_tab;
    OK
    jan    china    man
    mary    america    man
    lilei    china    man
    heyong    china    man
    yiku    japan    man
    emoji    japan    man
    Time taken: 0.076 seconds, Fetched: 6 row(s)
    复制代码

    查看par_tab目录结构

    [hadoop@hadoop001 files]$ hadoop dfs -lsr /user/hive/warehouse/par_tab
    
    drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:25 /user/hive/warehouse/par_tab/sex=man
    -rwxr-xr-x   1 hadoop supergroup         71 2017-03-29 08:25 /user/hive/warehouse/par_tab/sex=man/par_tab.txt

    可以看到,在新建分区表的时候,系统会在hive数据仓库默认路径/user/hive/warehouse/下创建一个目录(表名),再创建目录的子目录sex=man(分区名),最后在分区名下存放实际的数据文件。

    如果再插入另一个数据文件数据,如文件

    lily,china
    nancy,china
    hanmeimei,america

    插入数据

    load data local inpath '/home/hadoop/files/par_tab_wm.txt' into table par_tab partition (sex='woman');

    查看par_tab表目录结构

    [hadoop@hadoop001 files]$ hadoop dfs -lsr /user/hive/warehouse/par_tab
    drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:25 /user/hive/warehouse/par_tab/sex=man
    -rwxr-xr-x   1 hadoop supergroup         71 2017-03-29 08:25 /user/hive/warehouse/par_tab/sex=man/par_tab.txt
    drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:35 /user/hive/warehouse/par_tab/sex=woman
    -rwxr-xr-x   1 hadoop supergroup         41 2017-03-29 08:35 /user/hive/warehouse/par_tab/sex=woman/par_tab_wm.txt

    最后查看两次插入的结果,包含了man和woman

    复制代码
    hive> select * from par_tab;
    OK
    jan    china    man
    mary    america    man
    lilei    china    man
    heyong    china    man
    yiku    japan    man
    emoji    japan    man
    lily    china    woman
    nancy    china    woman
    hanmeimei    america    woman
    Time taken: 0.136 seconds, Fetched: 9 row(s)
    复制代码

    因为分区列是表实际定义的列,所以查询分区数据时

    hive> select * from par_tab where sex='woman';
    OK
    lily    china    woman
    nancy    china    woman
    hanmeimei    america    woman
    Time taken: 0.515 seconds, Fetched: 3 row(s)

    下面创建一张静态分区表par_tab_muilt,多个分区(性别+日期)

    复制代码
    hive> create table par_tab_muilt (name string, nation string) partitioned by (sex string,dt string) row format delimited fields terminated by ',' ;
    hive> load data local inpath '/home/hadoop/files/par_tab.txt' into table par_tab_muilt partition (sex='man',dt='2017-03-29');
    
    
    [hadoop@hadoop001 files]$ hadoop dfs -lsr /user/hive/warehouse/par_tab_muilt
    drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:45 /user/hive/warehouse/par_tab_muilt/sex=man
    drwxr-xr-x   - hadoop supergroup          0 2017-03-29 08:45 /user/hive/warehouse/par_tab_muilt/sex=man/dt=2017-03-29
    -rwxr-xr-x   1 hadoop supergroup         71 2017-03-29 08:45 /user/hive/warehouse/par_tab_muilt/sex=man/dt=2017-03-29/par_tab.txt
    复制代码

    可见,新建表的时候定义的分区顺序,决定了文件目录顺序(谁是父目录谁是子目录),正因为有了这个层级关系,当我们查询所有man的时候,man以下的所有日期下的数据都会被查出来。如果只查询日期分区,但父目录sex=man和sex=woman都有该日期的数据,那么Hive会对输入路径进行修剪,从而只扫描日期分区,性别分区不作过滤(即查询结果包含了所有性别)。

    动态分区

    如果用上述的静态分区,插入的时候必须首先要知道有什么分区类型,而且每个分区写一个load data,太烦人。使用动态分区可解决以上问题,其可以根据查询得到的数据动态分配到分区里。其实动态分区与静态分区区别就是不指定分区目录,由系统自己选择。

    首先,启动动态分区功能

    hive> set hive.exec.dynamic.partition=true;

    假设已有一张表par_tab,前两列是名称name和国籍nation,后两列是分区列,性别sex和日期dt,数据如下

    复制代码
    hive> select * from par_tab;
    OK
    lily    china    man    2013-03-28
    nancy    china    man    2013-03-28
    hanmeimei    america    man    2013-03-28
    jan    china    man    2013-03-29
    mary    america    man    2013-03-29
    lilei    china    man    2013-03-29
    heyong    china    man    2013-03-29
    yiku    japan    man    2013-03-29
    emoji    japan    man    2013-03-29
    Time taken: 1.141 seconds, Fetched: 9 row(s)
    复制代码

    现在我把这张表的内容直接插入到另一张表par_dnm中,并实现sex为静态分区,dt动态分区(不指定到底是哪日,让系统自己分配决定)

    hive> insert overwrite table par_dnm partition(sex='man',dt)
        > select name, nation, dt from par_tab;

    插入后看下目录结构

    drwxr-xr-x   - hadoop supergroup          0 2017-03-29 10:32 /user/hive/warehouse/par_dnm/sex=man
    drwxr-xr-x   - hadoop supergroup          0 2017-03-29 10:32 /user/hive/warehouse/par_dnm/sex=man/dt=2013-03-28
    -rwxr-xr-x   1 hadoop supergroup         41 2017-03-29 10:32 /user/hive/warehouse/par_dnm/sex=man/dt=2013-03-28/000000_0
    drwxr-xr-x   - hadoop supergroup          0 2017-03-29 10:32 /user/hive/warehouse/par_dnm/sex=man/dt=2013-03-29
    -rwxr-xr-x   1 hadoop supergroup         71 2017-03-29 10:32 /user/hive/warehouse/par_dnm/sex=man/dt=2013-03-29/000000_0

    再查看分区数

    hive> show partitions par_dnm;
    OK
    sex=man/dt=2013-03-28
    sex=man/dt=2013-03-29
    Time taken: 0.065 seconds, Fetched: 2 row(s)

    证明动态分区成功。

    注意,动态分区不允许主分区采用动态列而副分区采用静态列,这样将导致所有的主分区都要创建副分区静态列所定义的分区。

    动态分区可以允许所有的分区列都是动态分区列,但是要首先设置一个参数hive.exec.dynamic.partition.mode :

    hive> set hive.exec.dynamic.partition.mode;
    hive.exec.dynamic.partition.mode=strict

    它的默认值是strick,即不允许分区列全部是动态的,这是为了防止用户有可能原意是只在子分区内进行动态建分区,但是由于疏忽忘记为主分区列指定值了,这将导致一个dml语句在短时间内创建大量的新的分区(对应大量新的文件夹),对系统性能带来影响。
    所以我们要设置:

    hive> set hive.exec.dynamic.partition.mode=nostrick;

    如有错漏,请通知改正。

  • 相关阅读:
    flume sink两种类型 file_rool 自定义sing com.mycomm.MySink even if there is only one event, the event has to be sent in an array
    为什么引入进程20年后,又引入线程?
    As of Flume 1.4.0, Avro is the default RPC protocol.
    Google Protocol Buffer 的使用和原理
    Log4j 2
    统一日志 统一订单
    网站行为跟踪 Website Activity Tracking Log Aggregation 日志聚合 In comparison to log-centric systems like Scribe or Flume
    Percolator
    友盟吴磊:移动大数据平台的架构、实践与数据增值
    Twitter的RPC框架Finagle简介
  • 原文地址:https://www.cnblogs.com/zourui4271/p/12198466.html
Copyright © 2011-2022 走看看