hive 分区表 分桶表 详细介绍

张映 发表于 2020-01-15

分类目录: hadoop/spark/scala

标签:, ,

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

一,什么是分区和分桶

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

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

二,创建分区,分桶表

1,创建分区表

  1. create table `tank_test1` (  
  2. `log_time` int,  
  3. `aid` string,  
  4. `aid_name`  string,  
  5. `ip` string  
  6. )  
  7. PARTITIONED BY (log_date int)  
  8. ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE;  

2,创建分桶表

  1. create table `tank_test2` (  
  2. `log_date` int,  
  3. `log_time` int,  
  4. `aid` string,  
  5. `aid_name` string,  
  6. `ip` string  
  7. )  
  8. CLUSTERED BY(log_date) SORTED BY(log_date ASC) INTO 2 BUCKETS  
  9. ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n' STORED AS TEXTFILE;  

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

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

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

  1. hive> insert into tank_test1 partition (log_date)  
  2.  > select log_time,aid,aid_name,ip,log_date from user_info limit 1000000;  
  3.   
  4. hive> insert into tank_test2  
  5.  > select log_date,log_time,aid,aid_name,ip from user_info limit 1000000;  
  6.   
  7. hive> insert into tank_test3 partition (log_date)  
  8.  > select log_time,aid,aid_name,ip,log_date from user_info limit 1000000;  

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

四,表数据目录查看

  1. ├── tank_test1   //分区表  
  2. │   ├── log_date=20190903  
  3. │   │   └── 000000_0  
  4. │   ├── log_date=20190904  
  5. │   │   └── 000000_0  
  6. │   ├── log_date=20190905  
  7. │   │   └── 000000_0  
  8. │   └── log_date=20190906  
  9. │       └── 000000_0  
  10. ├── tank_test2  //分桶表  
  11. │   ├── 000000_0  
  12. │   └── 000001_0  
  13. └── tank_test3  //分区和分桶结合表  
  14.     ├── log_date=20190903  
  15.     │   ├── 000000_0  
  16.     │   └── 000001_0  
  17.     ├── log_date=20190904  
  18.     │   ├── 000000_0  
  19.     │   └── 000001_0  
  20.     ├── log_date=20190905  
  21.     │   ├── 000000_0  
  22.     │   └── 000001_0  
  23.     └── log_date=20190906  
  24.         ├── 000000_0  
  25.         └── 000001_0  

五,修改分区和分桶

1,修改分区

  1. hive> show partitions tank_test3;  
  2. OK  
  3. log_date=20190903  
  4. log_date=20190904  
  5. log_date=20190905  
  6. log_date=20190906  
  7. Time taken: 0.231 seconds, Fetched: 4 row(s)  
  8. hive> ALTER TABLE tank_test3 ADD PARTITION (log_date=20190907); //添加分区  
  9. OK  
  10. Time taken: 0.489 seconds  
  11. hive> show partitions tank_test3;  
  12. OK  
  13. log_date=20190903  
  14. log_date=20190904  
  15. log_date=20190905  
  16. log_date=20190906  
  17. log_date=20190907  
  18. Time taken: 0.188 seconds, Fetched: 5 row(s)  
  19. hive> ALTER TABLE tank_test3 PARTITION (log_date=20190907) RENAME TO PARTITION (log_date=20190908); //重命名分区  
  20. OK  
  21. Time taken: 1.998 seconds  
  22. hive> show partitions tank_test3;  
  23. OK  
  24. log_date=20190903  
  25. log_date=20190904  
  26. log_date=20190905  
  27. log_date=20190906  
  28. log_date=20190908  
  29. Time taken: 0.371 seconds, Fetched: 5 row(s)  
  30. hive> ALTER TABLE tank_test3 DROP IF EXISTS PARTITION (log_date=20190908); //删除分区  
  31. Dropped the partition log_date=20190908  
  32. OK  
  33. Time taken: 0.682 seconds  
  34. hive> show partitions tank_test3;  
  35. OK  
  36. log_date=20190903  
  37. log_date=20190904  
  38. log_date=20190905  
  39. log_date=20190906  
  40. Time taken: 0.196 seconds, Fetched: 4 row(s)  

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

2,修改分桶

  1. hive> set hive.enforce.bucketing = true; //强制使用分桶  
  2. hive> set map.reduce.tasks = 4;  //设置分桶数  
  3.   
  4. //以前是2个分桶  
  5. hive> dfs -ls /home/cdh6/hive/warehouse/tanktest.db/tank_test2;  
  6. Found 2 items  
  7. -rwxrwxrwt 2 root hive 46767339 2020-01-15 11:25 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000000_0  
  8. -rwxrwxrwt 2 root hive 6683039 2020-01-15 11:25 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000001_0  
  9.   
  10. //插入数据  
  11. hive> insert into tank_test2 select log_date,log_time,aid,aid_name,ip from user_info limit 2000000;  
  12.   
  13. //现在是4个分桶了  
  14. hive> dfs -ls /home/cdh6/hive/warehouse/tanktest.db/tank_test2;  
  15. Found 4 items  
  16. -rwxrwxrwt 2 root hive 46767339 2020-01-15 11:25 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000000_0  
  17. -rwxrwxrwt 2 root hive 71991116 2020-01-15 14:29 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000000_0_copy_1  
  18. -rwxrwxrwt 2 root hive 6683039 2020-01-15 11:25 /home/cdh6/hive/warehouse/tanktest.db/tank_test2/000001_0  
  19. -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