默认情况下,简单的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