hive 分区表 分桶表 详细介绍

张映 发表于 2020-01-15

分类目录: hadoop/spark/scala

标签:, ,

默认情况下,简单的HQL查询会扫描整个表。查询大表时,这会降低性能。可以通过创建分区来解决此问题。在Hive中,每个分区对应于预定义的分区列,这些分区列映射到HDFS中表的目录中的子目录。当查询表时,只读取表中所需的数据分区(目录),因此查询的I/O和时间大大减少。使用分区是提高Hive性能的一种非常简单有效的方法。

一,什么是分区和分桶

分区为HDFS上表目录的子目录,数据按照分区存储在子目录中。如果查询的 where 字句的中包含分区条件,则直接从该分区去查找,而不是扫描整个表目录,合理的分区设计可以极大提高查询速度和性能。

分区提供了一个隔离数据和优化查询的可行方案,但是并非所有的数据集都可以形成合理的分区,分区的数量也不是越多越好,过多的分区条件可能会导致很多分区上没有数据。同时 Hive 会限制动态分区可以创建的最大分区数,用来避免过多分区文件对文件系统产生负担。鉴于以上原因,Hive 还提供了一种更加细粒度的数据拆分方案:分桶表 (bucket Table)。
分桶表会将指定列的值进行哈希散列,并对 bucket(桶数量)取余,然后存储到对应的 bucket(桶)中。

二,创建分区,分桶表

1,创建分区表

create table `tank_test1` (
`log_time` int,
`aid` string,
`aid_name`  string,
`ip` string
)
PARTITIONED BY (log_date int)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE;

2,创建分桶表

create table `tank_test2` (
`log_date` int,
`log_time` int,
`aid` string,
`aid_name` string,
`ip` string
)
CLUSTERED BY(log_date) SORTED BY(log_date ASC) INTO 2 BUCKETS
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE;

3,创建分区与分桶混合表

create table `tank_test3` (
`log_time` int,
`aid` string,
`aid_name` string,
`ip` string
)
PARTITIONED BY (log_date int)
CLUSTERED BY(aid) SORTED BY(aid ASC) INTO 2 BUCKETS
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE;

三,分区,分桶表,插入数据

hive> insert into tank_test1 partition (log_date)
 > select log_time,aid,aid_name,ip,log_date from user_info limit 1000000;

hive> insert into tank_test2
 > select log_date,log_time,aid,aid_name,ip from user_info limit 1000000;

hive> insert into tank_test3 partition (log_date)
 > select log_time,aid,aid_name,ip,log_date from user_info limit 1000000;

在往分区表里面插入数据时,可以指定特定分区的。

四,表数据目录查看

├── tank_test1   //分区表
│   ├── log_date=20190903
│   │   └── 000000_0
│   ├── log_date=20190904
│   │   └── 000000_0
│   ├── log_date=20190905
│   │   └── 000000_0
│   └── log_date=20190906
│       └── 000000_0
├── tank_test2  //分桶表
│   ├── 000000_0
│   └── 000001_0
└── tank_test3  //分区和分桶结合表
    ├── log_date=20190903
    │   ├── 000000_0
    │   └── 000001_0
    ├── log_date=20190904
    │   ├── 000000_0
    │   └── 000001_0
    ├── log_date=20190905
    │   ├── 000000_0
    │   └── 000001_0
    └── log_date=20190906
        ├── 000000_0
        └── 000001_0

五,修改分区和分桶

1,修改分区

hive> show partitions tank_test3;
OK
log_date=20190903
log_date=20190904
log_date=20190905
log_date=20190906
Time taken: 0.231 seconds, Fetched: 4 row(s)
hive> ALTER TABLE tank_test3 ADD PARTITION (log_date=20190907); //添加分区
OK
Time taken: 0.489 seconds
hive> show partitions tank_test3;
OK
log_date=20190903
log_date=20190904
log_date=20190905
log_date=20190906
log_date=20190907
Time taken: 0.188 seconds, Fetched: 5 row(s)
hive> ALTER TABLE tank_test3 PARTITION (log_date=20190907) RENAME TO PARTITION (log_date=20190908); //重命名分区
OK
Time taken: 1.998 seconds
hive> show partitions tank_test3;
OK
log_date=20190903
log_date=20190904
log_date=20190905
log_date=20190906
log_date=20190908
Time taken: 0.371 seconds, Fetched: 5 row(s)
hive> ALTER TABLE tank_test3 DROP IF EXISTS PARTITION (log_date=20190908); //删除分区
Dropped the partition log_date=20190908
OK
Time taken: 0.682 seconds
hive> show partitions tank_test3;
OK
log_date=20190903
log_date=20190904
log_date=20190905
log_date=20190906
Time taken: 0.196 seconds, Fetched: 4 row(s)

在这里要注意,如果改变分区名称,里面的数据,也要做相应的改动。

2,修改分桶

hive> set hive.enforce.bucketing = true; //强制使用分桶
hive> set map.reduce.tasks = 4;  //设置分桶数

//以前是2个分桶
hive> dfs -ls /home/cdh6/hive/warehouse/tanktest.db/tank_test2;
Found 2 items
-rwxrwxrwt 2 root hive 46767339 2020-01-15 11:25 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000000_0
-rwxrwxrwt 2 root hive 6683039 2020-01-15 11:25 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000001_0

//插入数据
hive> insert into tank_test2 select log_date,log_time,aid,aid_name,ip from user_info limit 2000000;

//现在是4个分桶了
hive> dfs -ls /home/cdh6/hive/warehouse/tanktest.db/tank_test2;
Found 4 items
-rwxrwxrwt 2 root hive 46767339 2020-01-15 11:25 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000000_0
-rwxrwxrwt 2 root hive 71991116 2020-01-15 14:29 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000000_0_copy_1
-rwxrwxrwt 2 root hive 6683039 2020-01-15 11:25 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000001_0
-rwxrwxrwt 2 root hive 34985281 2020-01-15 14:30 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000001_0_copy_1

从这儿可以看出,可以通过改变分桶的数量,来减轻小文件的压力。

 



转载请注明
作者:海底苍鹰
地址:http://blog.51yip.com/hadoop/2350.html