如何对Hive表进行分桶分区操作
(1)问题分析
考官主要考核你对hive开发中分区分桶的理解,要讲出他们的概念,区别,以及使用场景。
(2)核心问题讲解
分区
分区是指按照数据表的某列或某些列分为多个区,区从形式上可以理解为文件夹,比如我们要收集某个大型网站的日志数据,一个网站每天的日志数据存在同一张表上,由于每天会生成大量的日志,导致数据表的内容巨大,在查询时进行全表扫描耗费的资源非常多。那其实这个情况下,我们可以按照日期对数据表进行分区,不同日期的数据存放在不同的分区,在查询时只要指定分区字段的值就可以直接从该分区查找。
分桶
分桶是相对分区进行更细粒度的划分。分桶将整个数据内容按照某列属性值的hash值进行区分,如要按照name属性分为3个桶,就是对name属性值的hash值对3取摸,按照取模结果对数据分桶。如取模结果为0的数据记录存放到一个文件,取模为1的数据存放到一个文件,取模为2的数据存放到一个文件。
区别
1)分桶随机分割数据库,分区是非随机分割数据库。因为分桶是按照列的哈希函数进行分割的,相对比较平均;而分区是按照列的值来进行分割的,容易造成数据倾斜。
2)分桶是对应不同的文件(细粒度),分区是对应不同的文件夹(粗粒度)。桶是更为细粒度的数据范围划分,分桶的比分区获得更高的查询处理效率,使取样更高效。
3)注意:普通表(外部表、内部表)、分区表这三个都是对应HDFS上的目录,桶表对应是目录里的文件。
(3)问题扩展
除了分区表分桶表之外,hive还有外部表和内部表。普通表(外部表、内部表)、分区表这三个都是对应HDFS上的目录,桶表对应是目录里的文件。
外部表(external table)
有external修饰,表数据保存在HDFS上,该位置由用户指定。删除表时,只会删除表的元数据,所以外部表不是有Hive完全管理的。
内部表(internal table/managed table)
使没有external修饰,表数据保存在Hive默认的路径下,数据完全由Hive管理,删除表时元数据和表数据都会一起删除。
区别
1)外部表的表数据由HDFS管理,Hive只管理外部表的元数据,而内部表的表数据和元数据都由Hive管理
2)外部表的表数据存储位置由用户指定,而内部表的数据默认存储位置为/apps/hive/warehouse/数据库名.db/数据文件名
3)删除外部表时,只会删除表的元数据,表数据仍然存储在HDFS中,删除内部表时,元数据和表数据都会删除
4)对内部表修改时会同步到元数据,而对外部表结构和分区修改时,需要进行修复msck rapair table table_name,外部表不能修改数据内容。
(4)结合项目中使用
在逻辑上分区表与未分区表没有区别,在物理上分区表会将数据按照分区键的列值存储在表目录的子目录中,目录名=“分区键的键值”。其中需要注意的是分区键的值不一定要基于表的某一列(字段),它可以指定任意值,只要查询的时候指定相应的分区键来查询即可。我们可以对分区进行添加、删除、重命名、清空等操作。因为分区在特定的区域(子目录)下检索数据,作为where查询条件,可以减少扫描成本。
分桶则是指定分桶表的某一列,让该列数据按照哈希取模的方式随机、均匀地分发到各个桶文件中。因为分桶操作需要根据某一列具体数据来进行哈希取模操作,故指定的分桶列必须基于表中的某一列(字段)。因为分桶改变了数据的存储方式,它会把哈希取模相同或者在某一区间的数据行放在同一个桶文件中。
如此一来便可提高查询效率,如:我们要对两张在同一列上进行了分桶操作的表进行JOIN操作的时候,只需要对保存相同列值的桶进行JOIN操作即可。同时分桶也能让取样(Sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便。