Hive 优化之为外部表创建分区
首先,我们有一个数据量很大的表。其次,对他进行条件查询或其他操作就像看着一只小蜗牛在爬。
是可忍,孰不可忍!
0x01 原理
关于分区为什么能提升查询速度,这就值得你仔细想想了。
既然 hive
基于文件系统,那么我们可以把它类比成很多个桶。
假设现在有 100 个桶,分别存放不同的海鲜,其中 2 个桶里有我们想要的桂花鱼,1 个桶里有阿根廷大红虾,那如何才能在最快的速度找出这 3 个桶?
按照默认的策略,人们会打开盖子一桶一桶找,而如果有 1000、10000 个桶,就会从一个人找演变成一群人一起找。
有没有改进方式呢?有。
有一天老板发现,不对啊,这个事我居然叫那么多人来做,感觉自己额外付出了很多成本,亏钱了。不行!这个事情必须改革!于是他思前想后好几天怎么也也想不到更好的办法,也因此懊恼了许久。直到有一天,老板夫人得了风寒,老板十分心急,替夫人去药铺抓药,当它看见郎中拿着方子在药柜抓药的时候,心中的郁结终于揭开了。拍了拍脑瓜子,大叫了声,对呀!我怎么没想到呢!
于是,从药铺回来后,老板更改了新的存鱼策略。它让员工们把鱼放进桶里的同时,在桶外贴上标签,取鱼的时候只需要远远地扫一眼就能快速定位。
hive
也是如此,你可以粗略地将它的存储系统理解为,将一堆文件放在同一个文件夹里,需要的时候在这堆文件里遍历,最后的效果不言而喻。
分区的好处便是,将文件按一定的维度,存进不同的文件夹,相当于给他们打好了标签,这样我按这个维度搜索时,便不需要遍历其他无关的文件。数据越多,对查询效率的提升就越大。
0x02 操作一波
首先看分区列表,如果结果为空就表示该表下没有分区。
1 | show partitions tmp.tmp_user; |
给当前表添加分区
1 | alter table tmp.tmp_user add partition (month='2018_10', day='25') location '/user/amos/tmp_user/month=2018_10/day=25'; |
将数据迁移至分区中
1 | hdfs dfs -mv /user/amos/tmp_user/data_20181025.csv /user/amos/tmp_user/month=2018_10/day=25 |
物极必反
为了提升搜索效果,增加分区数是可以的,但是如果分区数太过庞大,而需查询的数据也很多的话,分区带来的提升会被弱化。尤其是在分区中数据较为分散的时候,只要查询数据量达到一定量级便会轻易集中所有分区。
大量分区带来的不良后果不仅如此,还会在查询之后给磁盘带来更多的小文件。
说点题外话
如果是对数据仓库进行优化
在 hive
中,有几种办法
- 分区
- 分桶
- 索引
- 区分活跃用户
- 更改数据结构(id - string –> id - list
)