一、外部表和内部表的区别
(1)创建表时指定external关键字,就是外部表,不指定external就是内部表
(2)内部表删除后把元数据和数据都删除了,外部表删除后只是删除了元数据,不会删除hdfs上的数据文件
(3)外部表创建表时通过location指定存放表数据的hdfs上的路径,而内部表是默认存放在hive-site.xml中
设置的warehouse中,会在warehouse这个目录下以表名创建文件夹,数据就存放在这里。
二、.hive表分区
hive表分区其实就是分目录,表是大目录,分区是子目录,通过分区来实现分目录存放数据
分区由于是目录,不能带有特殊符号,分区列的值要转化为文件夹的存储路径,所以如果分区列的值中包含特殊值,如 '%', ':', '/', '#',它将会被使用%加上2字节的ASCII码进行转义,分区字段并不是表中真实存在的字段,而是一个或者多个伪列。表的数据文件中实际上并不保存分区列的信息与数据,而是用这个字段来划分数据的
存放目录,使用分区可以加快查询速度,查询时可以直接查询某一个分区下的数据,而不用管其他分区的数据
静态分区:
写入数据的时候就知道了(指定了)分区的名字
动态分区:
在写入数据的时候不知道分区的名字,当有符合分区条件的数据的时候会给它增加新的分区。
动态分区需要提前设置好连个参数,不然建分区的时候会抛异常
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nostrict;
动态分区:当select的结果记录数大于零的时候才会创建分区
静态分区只要指定了就一定会创建。
动态分区会为每一个分区配上reduce数。比如设置了set mapreduce.job.reduces=100.设置了reduce的个数。
当有两个分区,如果每一个结果集中都有数据,会为每一个分区配上100个reduce数,也就是namenode同时处理200个文件写操作,
这种操作如果在分区值很多的时候容易把namenode搞挂掉,因此写动态分区的时候要清楚分区的值和合理设置reduce的数量
三、分桶
桶是更细粒度的划分, 相同的数据分到一个桶里面,减少数据访问的量,对每一个表或者分区,hive可以进行进一步的分桶
对列的值哈希然后除以桶的个数求与的方式决定这条数据放到哪个桶里面去。
(1)分桶可以获得更高查询效率
(2)桶为表加上了额外的结构,hive查询的时候可以利用这种结构
两个表连接时相同的列上划分了桶的表可以使用map端进行连接,join连接时两个表有相同的列,如果这两个表都进行了桶的操作,那么这个保存相同列值得桶进行join操作就可以减少join的数量
分桶需要设置两个参数:
set hive.enforce.bucketing=true;
set hive.enforce.sorting=true;
四、数据
数据遵循的规则是相同数据尽量聚集在一起
这样数据访问时可以直接访问计算节点的本地数据,数据本地性,降低网络数据的流量和负载
数据存储方式
三种常用的方式:
seqencefile 压缩效率低,查询速度一般
textfile(默认存储方式)不做压缩,磁盘开销大,解析开销大,加载速度最快
rcfile (0.6.0之后支持) 压缩率最高,查询效率最高,数据加载最慢
另外还有
orc(0.11.0之后)
parquet(0.13.0)
avro(0.14.0)
inputformat