Hive基础(3):表分类、视图、数据加载方式、数据的导出、本地模式

========================================================================
复习:
1、加载数据的两种模式
读模式
数据被加载到数据库的时候,不对其合法性进行校验,只在查询等操作的时候进行校验,特点:加载速度快,适合大数据的加载
写模式
数据被加载到数据库的时候,需对其合法性进行校验,数据库中的数据都是合法的数据,特点:加载速度慢,但是查询速度快。
Hive采用的是读模式,数据被加载到数据库的时候,不对其合法性进行校验,对于在查询过程出现的非法数据显示为NULL。
2、Hive表中加载数据的两种方式
load data local inpath linux_fs_path into table tblName;
hadoop fs -put linux_path hdfs_uri;
3、Hive中复合数据类型和各种默认的分隔符:
复合数据类型:array、map、struct
array元素的引用:arrayName[index]
map元素的引用:mapName['key']
struct元素的引用:structName.item
默认分隔符:
行的默认分隔符:'\n'
列的默认分隔符:'\001' --> ctrl+v ctrl+a
集合元素的默认分隔符:'\002' --> ctrl+v ctrl+b
map k-v的默认分隔符:'\003' --> ctrl+v ctrl+c
在创建表写分隔符的时候,是有顺序要求的,如下:
create table tblName(
columns columns_type comment 'comment'
) row format delimited--->指明要使用自定义添加分隔符
fields terminated by '列分隔符'  -->读取数据的时候是一行一行的,读取好了一行之后,对数据解析,所以要用列分隔符拆分每一列
collection items terminated by '集合元素分割符' -->如果列是集合的话,就要跟着拆分集合元素
map keys terminated by 'map-key分割符' -->map 也是集合中的元素,碰到是map的类型了再解析map
lines terminated by '行分隔符'; -->解析完一行需要知道下一行,所以这个时候要知道行分隔符了
==========================================================================================
1、表的分类
受控表
所谓受控表,我们也经常叫内部表,和外部表对应起来,就是说表的数据的生命周期收表的控制,当表定义被删除的时候,表中的数据随之一并被删除。
创建一张表,其对应在hive中就有了表记录,在metastore表TBLS中就有表定义,当我们一旦从hive中删除一张表的定义之后,其表中的数据也就不复存在了,
在metastore中的定义也就不存在了
外部表
和受控表相对的,怎么相对呢,你的内部表的数据的生命周期受表定义的影响不是,外部表的不是这样的,数据的生命周期,
或者说数据存在与否和表的定义互不约束,表中的数据呢,只是表对hdfs上相应文件的一个引用而已,当删除表定义的时候,表中的数据依然存在。
如何创建外部表?
create external table tblName(colName colType...);
external,是外部表呀,必须要和内部表区别一下
加载数据
alter table tblName set location 'hdfs_absolute_uri';
一个是location,不是引用hdfs的数据吗,
当然在创建表的时候就可以告诉它引用数据的地方
create external table tblName(colName colType...) location 'hdfs_absolute_uri';
需要说明的是:在创建表的时候指定的hdfs_absolute_uri是一个目录
注意:内部表和外部表是可以进行转换的,只需要进行一些简单的设置就可以了
内——>外
alter table tblName set tblproperties('EXTERNAL'='TRUE');
外——>内
alter table tblName set tblproperties('EXTERNAL'='FALSE');
分区表
假设服务器集群每天都产生一个日志数据文件,把数据文件统一存储到HDFS中。我们如果想查询某一天的数据的话,hive执行的时候会对所有文件都扫描一遍,
判断是否是指定的日期。
   可以让日期作为一个子目录。当hive查询的时候,根据日期去判断子目录。然后扫描符合条件的子目录中的数据文件。
如何创建一张分区表?
只需要在之前的创建表后面加上分区字段就可以了,eg.
  create table tblName (
   id int comment 'ID',
   name string comment 'name' 
  ) partitioned by (dt date comment 'create time')
  row format delimited
  fields terminated by '\t';
如何加载数据?
load data local inpath linux_fs_path into table tblName partition(dt='2015-12-12'); 
上面的语句会在hive表tblName中自动创建一个分区,以dt='2015-12-12'为文件夹名称,下面存放上传的数据
相应的在metastore中的partitions中就有了相应的记录。
分区的一些操作:
查询分区中的数据:select * from tblName where dt='2015-12-13';(分区相当于where的一个条件)
手动创建一个分区:alter table tblName add partition(dt='2015-12-13');
查看分区表有哪些分区:show partitions tblName;
删除一个分区:alter table tblName drop partition(dt='2015-12-12');
多个分区如何创建?
和单分区表的创建类似:
  create table tblName (
   id int comment 'ID',
   name string comment 'name' 
  ) partitioned by (year int comment 'admission year', school string comment 'school name')
  row format delimited
  fields terminated by '\t';
同时也可以从hdfs上引用数据:
alter table tblName partition(year='2015', school='crxy') set location hdfs_uri;
注意:
必须得现有分区,必须要使用hdfs绝对路径
相应的分区下面没有数据对吧,你删了分区也不会影响原来的数据对不对,有点动态引用的意思。
桶表
桶表是对数据进行哈希取值,然后放到不同文件中存储。
  分桶是将数据及分解成更容易管理的若干部分的另一种技术。
  如果进行表连接操作,那么就需要对两张表的数据进行全扫描。非常耗费时间。可以针对连接字段进行优化。
  分桶这种情况下呢,对于相似的表中的数据进行比较的话就非常的方便了,只要对比相应的桶中的数据就可了。
如何创建桶表?
create table tblName_bucket(id int) clustered by (id) into 3 buckets;
说明:
clustered by :按照什么分桶
into x buckets:分成x个桶
如何加载数据?
不能使用load data这种方式,需要从别的表来引用
insert into table tblName_bucket select * from tbl_other;
注意:在插入数据之前需要先设置开启桶操作,不然插入数据不会设置为桶!!!
set hive.enforce.bucketing=true;
桶表的主要作用:
数据抽样
提高某些查询效率
==========================================================================================
2、视图
  Hive中,也有视图的概念,那我们都知道视图实际上是一张虚拟的表,是对数据的逻辑表示,只是一种显示的方式,主要的作用呢:
  1、视图能够简化用户的操作
  2、视图使用户能以多钟角度看待同一数据
3、视图对重构数据库提供了一定程度的逻辑独立性
4、视图能够对机密数据提供安全保护
5、适当的利用视图可以更清晰的表达查询
  那我们在Hive中如何来创建一个视图呢?
create view t_view as select * from otherTbl;
关于视图的几点说明:
1、只有视图的定义,没有相应的物理结构
也就是说只有在metastore中有和hdfs中的映射关系,在hdfs中没有相应的文件夹
2、操作
可以把视图当做表的一个衍伸,所以对hive表的各种操作,在视图上就有。
==========================================================================================
3、总结数据加载方式
说明:[]表示可有可无,<>表示必须要有
1°、从linux fs和hdfs中加载
load data [local] inpath 'path' [overwrite] into table tblName [partition_sepc];
几个关键字有无的说明:
local:
有:数据从本地path中加载,其中path可以是绝对路径,也可以是相对路径。
无:数据从hdfs上的相应路径path中移动数据到表tblName下,相当于hadoop fs -mv hdfs_uri_1 hdfs_uri_2
overwrite:
有:覆盖原来的数据,只保留新上传的数据。
无:在原来的目录下,在增加一个数据文件。
partition:
有:增加到相应的分区中
无:该表不是分区表
2°、从其他表中装载
insert table tblName select columns... from otherTblName;
关于overwrite的含义和上述是一致的。
唯一一点需要说明的是:
tblName表中的字段要和后面select查询的字段要保持一致!!!
注意:有一个特殊的地方就是,hive中存在着同一份数据多种处理
Hive本身提供了一个独特的语法,她可以从一个数据源产生多个数据聚合,而无需每次聚合都要重新扫描一次。对于大的数据输入集来说,这个优化可以节约非常可观的时间。
例如,下面这个两个查询都会从原表history读取数据,然后倒入到2个不同的表中:
hive> insert overwrite table sales
> select * from history where dt=’2016-01-16’;
hive> insert overwrite table credits
> select * from history where dt=’2016-01-17’;
上面的查询,语法是正确的,不过执行效率低下。而如下这个查询可以达到同样的目的,却只需要扫描history表一次就可以了:
hive> from history
> insert overwrite sales select * where dt=’2016-01-16’
> insert overwrite credits select * where dt=’2016-01-17’;
3°、通过动态分区装载数据
如果我们表的分区创建非常多的话,对于我们装载数据是一件非常麻烦的事,Hive提供动态分区来解决这个问题。
可以基于查询参数推断出需要创建的分区名称,相比的分区都是静态的,这里就称之为动态的分区。
怎么来弄呢?
INSERT overwrite TABLE t3 PARTITION(province='gs', city) 
SELECT t.province, t.city FROM temp t WHERE t.province='gs';
说明一下:静态分区必须出现在动态分区之前!!!
我想连province='gs'都省了?
报错了,需要我们开启动态分区的支持
set hive.exec.dynamic.partition=true;
set hive.exec.dynamic.partition.mode=nonstrict;
set hive.exec.max.dynamic.partitions.pernode=1000;
INSERT overwrite TABLE t3 PARTITION(province, city) 
SELECT t.province, t.city FROM temp t;
经验说明一点:
在创建分区的时候,最好不要创建过多的分区,如果分区过多的话,查询也是非常的慢的,就像在window下一个文件夹下面的文件过多会对我们的使用造成非常的不便的。
那么hive能支持多大的分区数呢,可以使用命令
set hive.exec.max.dynamic.partitions获取
遇到的问题:
Dynamic partition cannot be the parent of a static partition 'year'
加载数据的时候和分区的顺序有关联,动态分区不能作为静态的父目录
Cannot insert into target table because column number/types are different 'school': Table insclause-0 has 3 columns, but query has 4 columns.
两张表的结构是相似的,插入的时候字段发生冲突了,需要加表的别名来区分。 
4、创建表的同时装载数据
和之前创建视图的时候的语法非常相似,把view改成table就可以
eg.create table newTblName as select columns from other_tblName;
==========================================================================================
4、数据的导出
这个是数据装载的反向过程,有两种方式
1°、在hdfs的直接上操作
hadoop fs -cp src_uri dest_uri
2°、在终端使用directory
insert overwrite [local] directory 'linux_fs_path' select ...from... where ...;
==========================================================================================
5、本地模式
之前有些hql语句的执行最后转化为了mr,但是执行的过程非常的慢,如何提高执行效率呢?使用本地模式。
需要开启本地模式:
set hive.exec.mode.local.auto=true;
再去执行相同的hql时,会发现速度提高很多。
但是,本地模式主要用来做调试,不能配置到hive-site.xml中,因为本地模式,会只在当前机器上
执行mr,但是如果数据量一大,这样会累垮我们的单台节点的。
==========================================================================================

你可能感兴趣的:(hive)