默认情况下,简单的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
从这儿可以看出,可以通过改变分桶的数量,来减轻小文件的压力。