hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行。
Metastore (hive元数据)
Hive将元数据存储在数据库中,比如mysql 、derby。Hive中的元数据包括表的名称,表的列和分区及其属性,表的数据所在的目录。
Hive数据存储在HDFS,大部分的查询、计算由mapreduce完成
Hive数据仓库于数据库的异同
(1)由于Hive采用了SQL的查询语言HQL,因此很容易将Hive理解为数据库。其实从结构上来看,Hive和数据库除了拥有类似的查询语言, 再无类似之处。 (2)数据存储位置。 hdfs raw local fs (3)数据格式。 分隔符 (4)数据更新。hive读多写少。Hive中不支持对数据的改写和添加,所有的数据都是在加载的时候中确定好的。 INSERT INTO … VALUES添加数据,使用UPDATE … SET修改数据 不支持的 HDFS 一次写入多次读取 (5)执行。hive通过MapReduce来实现的 而数据库通常有自己的执行引擎。 (6)执行延迟。由于没有索引,需要扫描整个表,因此延迟较高。另外一个导致Hive执行延迟高的因素是MapReduce框架 (7)可扩展性。 (8)数据规模。
hive几种基本表类型:内部表、外部表、分区表、桶表
内部表(管理表)和外部表的区别:
创建表
外部表创建表的时候,不会移动数到数据仓库目录中(/user/hive/warehouse),只会记录表数据存放的路径
内部表会把数据复制或剪切到表的目录下
删除表
外部表在删除表的时候只会删除表的元数据信息不会删除表数据
内部表删除时会将元数据信息和表数据同时删除
表类型一、管理表或内部表Table Type: MANAGED_TABLE
create table if not exists dept( deptno int, deptname string, address string ) row format delimited fields terminated by '\t'; //加载HDFS文件到Hive表中 load data inpath '/input/dept.txt' into table dept; //用来指定原文件的列分隔符 row format delimited fields terminated by '\t'; load 如果操作的HDFS上的文件,代表着会移动或者剪切文件 desc formatted dept; //描述表结构信息 Location: hdfs://bigdata/user/hive/warehouse/db01.db/dept Table Type: MANAGED_TABLE
表类型二、外部表
create external table emp( empno int, empname string, empjob string, mgno int, birthday string, salary float, bonus float, depno int ) row format delimited fields terminated by '\t' location '/input/demo'; //描述表结构 desc formatted emp; Location: hdfs://bigdata/input/demo Table Type: EXTERNAL_TABLE 删除内部表 drop table dept; 删除外部表 drop table emp; 清空表数据 truncate table student;
表类型三、分区表
分区表创建表的时候需要指定分区字段,分区字段与普通字段的区别:分区字段会在HDFS表目录下生成一个分区字段名称的目录,而普通字段则不会,查询的时候可以当成普通字段来使用,一般不直接和业务直接相关。
create table emp_part( empno int, empname string, empjob string, mgrno int, birthday string, salary float, bonus float, deptno int ) partitioned by (province string) row format delimited fields terminated by '\t'; //向分区表加载数据 load data local inpath '/home/user01/emp.txt' into table emp_part partition (province='CHICAGO'); //描述表信息 desc formatted emp_part; //查询全表数据 select * from emp_part; //查询分区字段表数据 select * from emp_part where province='CHICAGO'; //查看分区信息 show partitions emp_part; //增加分区 aler table emp_part add [if not exist] partition(provine='zhejiang',city='hangzhou') //删除分区 aler table emp_part drop [if exist] partition(provine='zhejiang',city='hangzhou')
外部分区表
create external table dept_part( deptno int, deptname string, address string ) partitioned by (province string) row format delimited fields terminated by '\t' location '/input/demo'; //手动增加分区字段及外部目录: alter table dept_part add partition (province='BOSTON') location '/input/demo/BOSTON'; //手动增加分区字段(自动生成分区目录) alter table dept_part add partition (province='NEW YORK');
表类型四:桶表
将内部表,外部表和分区表进一步组织成桶表
可以将表的列通过Hash算法进一步分解成不同的文件存储
create external table dept_part( deptno int, deptname string, address string ) partitioned by (province string) row format delimited fields terminated by '\t' location '/input/demo'; //手动增加分区字段及外部目录: alter table dept_part add partition (province='BOSTON') location '/input/demo/BOSTON'; //手动增加分区字段(自动生成分区目录) alter table dept_part add partition (province='NEW YORK');
创建表的方式
方式一 create + load
create [external] table table_name( col1_name col1_type, ... coln_name coln_type ) row format delimited fields terminated by '\t'; //load加载数据 laod data [local] inpth '本地文件(linux)/HDFS' [overwrite] into table table_name;
方式二 like + load
//复制表结构 create table tableB like tableA; //首先必须要有tableA //load加载数据 laod data [local] inpth '本地文件(linux)/HDFS' [overwrite] into table table_name;
方式三 as 创建表的同时加载数据
create table tableB row format delimited filelds termianted by ',' as select * from tableA; //首先必须要有tableA create table emp_as row format delimited fields terminated by ',' as select empno,empname,salary from emp_part1;
方式四 create + insert
//创建表 create table emp_insert( id int, name string, job string, salary float ) row format delimited fields terminated by ','; //insert into 加载数据 insert into table emp_insert select empno,empname,empjob,salary from emp_part1 where day='20170308' and hour='14';
加载数据的方式
加载方式一
//加载本地文件到Hive表 --使用存储介质(移动硬盘) laod data local inpth '本地文件(linux)' [overwrite] into table table_name;
加载方式二
//加载HDFS文件到hive表 --通过Flume等日志收集框架 laod data inpth 'HDFS文件' [overwrite] into table table_name;
加载方式三
//加载数据示覆盖已有的数据 laod data [local] inpth '文件' overwrite into table; //**hdfs dfs -put 本地目录及文件 表在HDFS所在的目录 desc formatted table_name; --找到table_name在HDFS上的目录
加载方式四
//创建表时通过select查询语句加载数据 create table tableB row format delimited filelds termianted by ',' as select * from tableA;
加载方式五
//先创建表,通过insert into table table_namea select * fom tableB
加载方式六
//创建外部表示通过location指定数据所在目录 create extrnal table_name( col1_name col1_type, ... coln_name coln_type ) row format delimited fields terminated by '\t'; location 'HDFS上的目录'
几种导出数据的方式
1.insert overwrite ... 导出到本地目录 insert overwrite local directory '/home/user01/export' row format delimited fields terminated by ' ' select * from emp_part1; 2.insert overwrite ... 导出到HDFS之上 insert overwrite directory '/export' select * from emp_part1 where day='20170308'; 3.hive -e 'HQL query' >> test bin/hive -e 'select * from db01.student' >> test.txt 4)sqoop
Hive 自定义函数函数
UDF 一进一出 处理原文件内容某些字段包含 [] “”
UDAF 多进一出 sum() avg() max() min()
UDTF 一进多出 ip -> 国家 省 市
Hive4种排序
1.order by //可以指定desc 降序 asc 升序
order by会对输入做全局排序,因此只有一个Reducer(多个Reducer无法保证全局有序),然而只有一个Reducer,会导致当输入规模较大时,消耗较长的计算时间。
2.sort by 【对分区内的数据进行排序】
sort by不是全局排序,其在数据进入reducer前完成排序,因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只会保证每个reducer的输出有序,并不保证全局有序。sort by不同于order by,它不受Hive.mapred.mode属性的影响,sort by的数据只能保证在同一个reduce中的数据可以按指定字段排序。使用sort by你可以指定执行的reduce个数(通过set mapred.reduce.tasks=n来指定),对输出的数据再执行归并排序,即可得到全部结果。
3.distribute by 【对map输出进行分区】
distribute by是控制在map端如何拆分数据给reduce端的。hive会根据distribute by后面列,对应reduce的个数进行分发,默认是采用hash算法。sort by为每个reduce产生一个排序文件。在有些情况下,你需要控制某个特定行应该到哪个reducer,这通常是为了进行后续的聚集操作。distribute by刚好可以做这件事。因此,distribute by经常和sort by配合使用。