hive的数据 存储:
首先弄清楚什么是元数据和表数据:元数据就是表的属性数据,表的名字,列信息,分区等标的属性信息,它是存放在RMDBS传统数据库中的(如,mysql)。表数据就是表中成千上万条数据了。
hive的存储过程:启动hive时,会初始化hive,这时会在mysql中生成大约36张表(后续随着业务的复杂会增加),然后创建表,会在mysql中存放这个表的信息(不是以表的形式存在的,而是把表的属性以数据的形式放在mysql中,这样在hive中使用sql命令一样是能够查到这张表的)。然后把本地的文本文件使用hive命令格式化导入到表中,这样这些数据就存放到hdfs中,而不是在mysql或hive中。
内部表,
hive> create table student(id int, name string, sex string, age int, department string) row format delimited fields terminated by ",";
我创建了一个studetn表,在mysql中是看不到这个表的:
说明没问题。
———————————————————————————————————
外部表案例(这里就使用网友大神的博文,更美观):
0: jdbc:hive2://hadoop3:10000> create external table student_ext (id int, name string, sex string, age int,department string) row format delimited fields terminated by "," location "/hive/student"; No rows affected (0.248 seconds)
——————————————————————————————————————————–
内部表外部表区别:
首先二者不是共存关系也不是修改关系,而是一开始创建表的使用要想好你到底需要什么样的表。
然后, 1、在导入数据到外部表,数据并没有移动到自己的 数据仓库目录下(如果指定了location的话),也就是说外部表中的数据并不是由它自己来管理的!而内部表则不一样;
2、在删除内部表的时候,Hive将会把属于表的元数据和数据全部删掉;而删除外部表的时候,Hive仅仅删除外部表的元数据,数据是不会删除的!
3. 在创建内部表或外部表时加上location 的效果是一样的,只不过表目录的位置不同而已,加上partition用法也一样,只不过表目录下会有分区目录而已,load data local inpath直接把本地文件系统的数据上传到hdfs上,有location上传到location指定的位置上,没有的话上传到hive默认配置的数据仓库中。
外部表相对来说更加安全些,数据组织也更加灵活,方便共享源数据。
那么,应该如何选择使用哪种表呢?在大多数情况没有太多的区别,因此选择只是个人喜好的问题。但是作为一个经验,如果所有处理都需要由Hive完成,那么你应该创建表,否则使用外部表!
—————————————————————————————————–
分区表:
0: jdbc:hive2://hadoop3:10000> create external table student_ptn(id int, name string, sex string, age int,department string) . . . . . . . . . . . . . . .> partitioned by (city string) . . . . . . . . . . . . . . .> row format delimited fields terminated by "," . . . . . . . . . . . . . . .> location "/hive/student_ptn"; No rows affected (0.24 seconds)
添加分区
0: jdbc:hive2://hadoop3:10000> alter table student_ptn add partition(city="beijing"); No rows affected (0.269 seconds) 0: jdbc:hive2://hadoop3:10000> alter table student_ptn add partition(city="shenzhen"); No rows affected (0.236 seconds) 0: jdbc:hive2://hadoop3:10000>
为什么要使用分区表呢?
看上面的例子很显然,这是个学生表,然后以城市分区,这样就能够根据学生所在市不同把不同的分区分在表中不同的子文件夹中.这样数据也就在不同的磁盘文件中,数据库对不同的分区会进行单独的管理,优化,最终的目的是加快我们数据查询的速度。
--------------------------------------------------------------------------------------------------------------------------------
最后还有个桶,这个有点难理解,就不做多说了就放个案例吧:
0: jdbc:hive2://hadoop3:10000> create external table student_bck(id int, name string, sex string, age int,department string) . . . . . . . . . . . . . . .> clustered by (id) sorted by (id asc, name desc) into 4 buckets . . . . . . . . . . . . . . .> row format delimited fields terminated by "," . . . . . . . . . . . . . . .> location "/hive/student_bck";
———————————————
增加 桶:
桶表(bucket table): 原理:
分区表是按照经常查询的字段做不同的分区,查询时就可以按分区进行查了.这样可以减小全局扫描提高查询的速度.分区表的缺陷就是选定了分区字段之后,结果会造成数据偏差特别大,有的分区数据特别大,有的分区数据特别小,这个时候作业的整个查询时间就受制于分区中数据特别大的那个分区,对整个作业的运行效率是不好的. 桶表和分区表的区别在于:不是按照业务字段来进行分区,对里面的记录做一个hash,记录做完hash之后就没有规律了,可以简单的认为数据做完hash之后都不相同,然后我们让数据进行模10,数据就被分成了十份,模100就被分成100份,因为hash值几乎各不相同,所以模后的结果,分成10份或者100份,每一份的数据量几乎是一样多的,当你hash之后然后模一个数字,分的那些数据量,每一份应该是差不多的,如果这样的话,我们把这样的数据存起来,模5,10,100 模的这个数字叫做桶,模几就分成几个桶,桶实际上就是模的数字,我们的记录就被划分到这个桶里面了,那么hive在进行查询的时候就会按照5个桶或者10个桶来进行处理,这样的话,好处是各个map运行的时间差不多 . 桶表用的领域很少,一般用在表连接 中,有两个表,有一个外键是连接字段,我们的这一个表里面的字段和另外一个的连接字段的值是相同的,hash后的值应该也相同,分桶的话会分到相同的桶中,在进行表连接的时候就比较方便了,只需要把对应的桶的数据连接一下然后再从里边查数据就方便了.
还有一个优点就是在进行抽样查询的时候,我们的记录只有10亿条记录,要查一下北京的有多少个,没必要把十亿条记录全扫一遍,但是可以扫一万或者一百万看一下北京的有多少,然后就可以大体的判断一下北京的大约占多少百分比了.抽样不需要一个准确的值,只需要一个样本就可以了,这样样本只要符合统计学上的大小就可以了,那么我们在进行抽样的话,如果按照桶表来进行抽样更合理,如果按时间抽,统计结果就不准了.
创建桶表:
create table bucket_table(id int ,name string) clustered by(id) into 3 buckets;
加载数据:
需要计算id的hash值,分桶.所以不能使用load data,load data加载方式是直接把数据从我们的磁盘复制到hdfs目录下,但是我们的分桶需要计算,计算需要走mapreduce,所以需要通过这种方式走mapreduce
设置启用桶 set hive.enforce.bucketing=true ; insert overwrite table bucket_table select id,name from jiuye;
分桶之后是三个文件,分区表是文件夹.桶表和分区表目的都是为了把数据进行划分 ,只是划分的方式不一样,一个是从业务字段 的角度来划分,一个是抛弃了业务字段从纯数据 的角度来进行划分,纯数据的角度和查询就不搭界了,主要就是用于抽样,表连接 .