共计 10186 个字符,预计需要花费 26 分钟才能阅读完成。
what’s
Hive 是由 Facebook 开发的构建在 Hadoop 之上的数据仓库平台。
它本身并不存储和处理数据,依赖于 HDFS 存储数据,依赖 MR 处理数据。而 hive 提供了一个类似 sql 的查询语言 HiveQL 来进行查询、变换数据等操作。当然 HiveQL 语句的底层是转换为相应的 mapreduce 代码进行执行,一般采用批处理的方式对海量数据进行处理。
设计目标就是将 hadoop 上的数据可以执行 SQL 操作。
让熟悉 SQL 编程的开发人员能够轻松的向 Hadoop 平台上转移。
数据仓库存储的是静态数据,很适合采用 MR 进行批处理。Hive 还提供了一系列对数据进行提取、转换、加载的工具,可以存储、查询和分析存储在 HDFS 上的数据。
特点
是分布式的关系型数据库。主要用来并行分布式处理大量数据。hive 中的所有查询除了 select * from table;
都是需要通过 MapReduce 的方式来执行的。
由于要走 MapReduce(8088mr 监控端口号),即使一个只有 1 行 1 列的表,如果不是通过 select * from table; 方式来查询的,可能也需要 8、9 秒。
但 hive 比较擅长处理大量数据。当要处理的数据很多,并且 Hadoop 集群有足够的规模,这时就能体现出它的优势。
与 mysql 等数据库比较
1、查询语言
由于 SQL 被广泛的应用在数据仓库中,因此,专门针对 Hive 的特性设计了类 SQL 的查询语言 HQL。熟悉 SQL 开发的开发者可以很方便的使用 Hive 进行开发。
2、数据存储位置
hive 的数据都是存储在 HDFS 中的。而 mysql 数据库则可以将数据保存在本地文件系统中。
3、数据格式
hive 中没有定义专门的数据格式,数据格式可以由用户指定,用户定义数据格式需要指定三个属性:列分隔符(通常为空格、”t”、”x001″)、行分隔符(”n”)以及读取文件数据的方法(Hive 中默认有三个文件格式 TextFile,SequenceFile 以及 RCFile)。由于在加载数据的过程中,不需要从用户数据格式到 Hive 定义的数据格式的转换,因此,Hive 在加载的过程中不会对数据本身进行任何修改,而只是将数据内容复制或者移动到相应的 HDFS 目录中。
而在数据库中,不同的数据库有不同的存储引擎,定义了自己的数据格式。所有数据都会按照一定的组织存储,因此,数据库加载数据的过程会比较耗时。
4、数据更新
由于 hive 是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,hive 中 不支持对数据的改写(hive(0.14) 后支持)和添加
,所有的数据都是在加载的时候中确定好的。而数据库中的数据通常是需要经常进行修改的,因此可以添加、修改数据。
5、索引
因为 hive 在加载数据的过程中不会对数据进行任何处理,甚至不会对数据进行扫描,因此也没有对数据中的某些 Key 建立索引。hive 要访问数据中满足条件的特定值时,需要暴力扫描整个数据,因此访问延迟较高。
不过由于 MapReduce 的引入,hive 可以并行访问数据,因此即使没有索引,对于大数据量的访问,hive 仍然可以体现出优势。
数据库中,通常会针对一个或者几个列建立索引,因此对于少量的特定条件的数据的访问,数据库可以有很高的效率,较低的延迟。由于数据的访问延迟较高,决定了 hive 不适合在线数据查询
。
6、执行
hive 中大多数查询的执行是通过 Hadoop 提供的 MapReduce 来实现的(类似 select * from tbl 的查询不需要 MapReduce)。
而数据库通常有自己的执行引擎。
7、执行延迟
之前提到 hive 在查询数据的时候,由于没有索引,需要扫描整个表,因此延迟较高。另外 一个导致 hive 执行延迟高的因素是 MapReduce 框架。由于 MapReduce 本身具有较高的延迟,因此在利用 MapReduce 执行 hive 查询时,也会有较高的延迟。
相对的,数据库的执行延迟较低。当然,这个低是有条件的,即数据规模较小,当数据规模大到超过数据库的处理能力的时候,hive 的并行计算显然能体现出优势。
8、可扩展性
由于 hive 是建立在 Hadoop 之上的,因此 Hive 的可扩展性是和 Hadoop 的可扩展性是 一致的。
而数据库由于 ACID 语义的严格限制,扩展行非常有限。目前最先进的并行数据库 Oracle 在理论上的扩展能力也只有 100 台左右。
9、数据规模
由于 Hive 建立在集群上并可以利用 MapReduce 进行并行计算,因此可以支持很大规模的数据.
数据库可以支持的数据规模较小。
数据仓库与数据库的区别
数据库是面向事务的设计,数据仓库是面向主题设计的。
数据库一般存储在线交易数据,数据仓库存储的一般是历史数据。
数据库设计是尽量避免冗余,一般采用符合范式的规则来设计,数据仓库在设计是有意引入冗余,采用反范式的方式来设计。
数据库是为捕获数据而设计,数据仓库是为分析数据、用于支持管理决策而设计,它的两个基本的元素是维表和事实表。(维是看问题的角度,比如时间,部门,维表放的就是这些东西的定义,事实表里放着要查询的数据,同时有维的 ID)
与 hbase 比较
1、hive 是分布式的关系型数据库,而 hbase 是分布式的非关系型的。
2、hive 是面向行存储的数据库,而 hbase 是面向列的数据库。
3、hive 支持类 sql 语言,通过数据库的方式来操作 hdfs 文件系统,为了简化编程,底层计算方式为 mapreduce。而 hbase 的 Shell 命令是以 JRuby 为核心编写的,不支持 sql。
4、hive 本身不存储和计算数据,它完全依赖于 HDFS 和 MapReduce,hive 中的表纯逻辑;而 hbase 是为查询而生的,它通过组织起节点內所有机器的內存,提供一個超大的內存 Hash 表,是物理表。
5、hive 是高延迟、结构化和面向分析的常用于离线分析业务,hbase 是低延迟、非结构化和面向编程的,常用于在线业务。
6.hive 可以认为是 map-reduce 的一个包装。hive 的意义就是把好写的 hive 的 sql 转换为复杂难写的 map-reduce 程序。而 hbase 可以认为是 hdfs 的一个包装。他的本质是数据存储,是个 NoSql 数据库;hbase 部署于 hdfs 之上,并且克服了 hdfs 在随机读写方面的缺点。
三个组成模块
用户接口模块
含 CLI、WebUI、JDBC、Thrift Server 等,用来实现对 Hive 的访问。
CLI 是 Hive 自带的命令行界面 hive shell;WebUI 是 Hive 的一个简单网页界面;JDBC、ODBC 以及 Thrift Server 可向用户提供进行编程的接口,其中 Thrift Server 是基于 Thrift 软件框架开发的,提供 Hive 的 RPC 通信接口。
元数据存储模块(Metastore)
是一个独立的关系型数据库,通常与 MySQL 数据库连接后创建的一个 MySQL 实例,也可以是 Hive 自带的 Derby 数据库实例。此模块主要保存表模式和其他系统元数据,如表的名称、表的列及其属性、表的分区及其属性、表的属性、表中数据所在位置信息等。
驱动模块(Driver)
含解析器、编译器、优化器、执行器等,负责把 HiveQL 语句转换成一系列 MR 作业,所有命令和查询都会进入驱动模块,通过该模块的解析变异,对计算过程进行优化,然后按照指定的步骤执行。
解析器:将 sql 字符串转换成抽象语法树 AST,一般用第三方工具库如 antlr 完成。然后对 AST 进行语法分析,如表是否存在、字段是否存在、sql 语义是否有误。
编译器:将 AST 编译生成逻辑执行计划。
优化器:多逻辑执行计划进行优化;
执行器:把逻辑执行计划转换成可以运行的物理计划,即 mapreduce/spark/tez。
有些查询不会走 mapreduce,如 select * from tbl
安装配置
http://sishuok.com/forum/blog…
hive 数据
数据类型
HQL 支持基本类型和复杂类型两大类数据类型。基本类型包括 TINYINT(1byte), SMALLINT(2byte), INT(4byte), BIGINT(8byte), FLOAT(4byte), DOUBLE(8byte), BOOLEAN(-), STRING(2G)。复杂类型包括 ARRAY(一组有序数组,类型必须一致), MAP(无序键值对,键值内部字段类型必须相同,而且要求 key 的类型为基本数据类型), STRUCT(一组字段,类型任意)。
数据的压缩
hive 中的压缩格式 RCFile、TextFile、SequenceFile。
采用 RCfile 的格式读取的数据量(373.94MB)远远小于 sequenceFile 的读取量(2.59GB)
执行速度前者 (68 秒) 比后者 (194 秒) 快很多
snappy 的执行进度远远高于 bz 的执行进度。
在 hive 中使用压缩需要灵活的方式,如果是数据源的话,采用 RCFile+bz 或 RCFile+gz 的方式,这样可以很大程度上节省磁盘空间;而在计算的过程中,为了不影响执行的速度,可以浪费一点磁盘空间,建议采用 RCFile+snappy 的方式,这样可以整体提升 hive 的执行速度。
至于 lzo 的方式,也可以在计算过程中使用,只不过综合考虑(速度和压缩比)还是考虑 snappy 适宜。
hive Cli
show
主要作用是查看 database、table、function 等组件的名称信息,也就是通过 show 命令我们可以知道我们的 hive 中有那些 database;当前 database 中有那些 table。等等。和 mysql 的 show 命令类型。show databases ;
数据库 show databases like 'db_hive*' ;
show tables ;
show create table 表名;
得到创建该表的语句
show functions ;
查看自带函数
describe
主要作用是获取 database、table、partition 的具体描述信息,包括存储位置、字段类型等信息。desc database db_hive_03 ;
desc database extended db_hive_03 ;
desc student ;
看表结构 desc extended student ;
看表完整信息,但比较乱 desc formatted student ;
看格式化的信息,常用
desc function upper ;
看函数 upper 的使用说明 desc function extended upper ;
看函数的案例演示select id ,upper(name) uname from db_hive.student ;
create
创建数据库
create database db_hive_01 ;
create database if not exists db_hive_02 ;
标准 create database if not exists db_hive_03 location '/user/cyan/hive/warehouse/db_hive_03.db' ;
默认是 /user/hive/,没有会自动创建
use db_hive;
当前使用数据库,否则用数据库名. 表名
创建表
简单如:create table student(id int, name string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
制表符分隔各行数据。
复杂一点:
create table IF NOT EXISTS default.log_20150913(
ip string COMMENT 'remote ip address' ,
user string ,
req_url string COMMENT 'user request url')
COMMENT 'BeiFeng Web Access Logs'
ROW FORMAT DELIMITED FIELDS TERMINATED BY ' '
STORED AS TEXTFILE ;// 以文本文件形式保存,列中的分隔符是空格,行中的分隔符回车
[ROW FORMAT row_format], row_format 格式:delimited fields terminated by '\001' collection terminated by '\002' map keys terminated by '\003' lines terminated by '\004' NULL DEFINED AS '\N'
[STORED AS file_format], file_format 格式:sequencefile
textfile(default)
rcfile
orc
parquet
avro
create table IF NOT EXISTS default.log_20150913_sa AS select ip,req_url from default.log_20150913 ;
AS sselect 来自另外一张表(分表),利用其他表的格式 like:create table if not exists default.dept_like like default.dept ;
eg: 创建员工表
create table IF NOT EXISTS default.emp(
empno int,
ename string,
job string,
mgr int, 上级
hiredate string, 入职时间
sal double,
comm double, 奖金
deptno int 部门
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
eg: 创建部门表
create table IF NOT EXISTS default.dept(
deptno int,
dname string,
loc string
)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
load
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)];
local 本地数据,不加则是 hdfs 数据
partition (partcol1=val1,…)分区表加载,特殊性
eg:load data local inpath '/opt/datas/student.txt'into table student ;
加载数据 utf- 8 格式 load data local inpath '/opt/datas/student1.txt' overwrite into table student ;
覆盖原数据,默认是追加
insert
创建表时通过 insert 加载数据
create table default.emp_ci like emp ;
insert into table default.emp_ci select * from default.emp ;
导出数据
insert overwrite local directory '/opt/datas/hive_exp_emp' select * from default.emp ;
导出数据到本地 insert overwrite directory '/user/beifeng/hive/hive_exp_emp' select * from default.emp ;
导出数据到 hdfs
导出数据到本地并定义格式
insert overwrite local directory '/opt/datas/hive_exp_emp2'
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' COLLECTION ITEMS TERMINATED BY '\n'
select * from default.emp ;
location
创建表的时候通过 location 指定加载数据
CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
LIKE existing_table_or_view_name
[LOCATION hdfs_path];
import
将外部数据导入 hive 表中
create table db_hive.emp like default.emp ;
import table db_hive.emp from '/user/beifeng/hive/export/emp_exp';
export
EXPORT TABLE default.emp TO '/user/beifeng/hive/export/emp_exp' ;
将 Hive 表中的数据,导出到外部(HDFS)
其他导出数据方式
1.hive shellbin/hive -e "select * from default.emp ;" > /opt/datas/exp_res.txt
2.sqoop
alter
alter table dept_like rename to dept_like_rename ;
改表名
也可以加列名
drop
drop database if exists db_hive_03 ;
非空就不能删 drop database db_hive_03 cascade;
非空能删,目录也被删了 drop database if exists db_hive_03 ;
清除表里的数据:truncate table db_hive_03 ;
select
select * from student ;
没有走 mapreduceselect id from student ;
走 MR
官网 LanguageManual 中:
[WITH CommonTableExpression (, CommonTableExpression)*]
SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT number]
select * from emp
where
GROUP BY
LIMIT number
from 语句主要是指定从那个数据表中查询数据,有两种使用方式:分别可以在 select 后和 with 后 &select 前使用,语法格式:
[with ...] select ... from ...
[with ...] from ... select ...
示例:select * from students;
from students select *;
子查询
hive 对子查询的支持有限,只支持嵌套 select 子句,而且只能在 from 和 with 语句块中使用子查询。语法规则如下:.... from (select statement) [[as] tmp_name]....
limit、= >= <= between and
select * from emp limit 5 ;
select t.empno, t.ename, t.deptno from emp t where t.sal between 800 and 1500 ;
is null / is not null /in /not in
select t.empno, t.ename, t.deptno from emp t where comm is null ;
max/min/count/sum/avg
select count(*) cnt from emp ;
select max(sal) max_sal from emp ;
select sum(sal) from emp ;
select avg(sal) from emp ;
group by
eg: 每个部门的平均工资select t.deptno, avg(t.sal) avg_sal from emp t group by t.deptno ;
eg: 每个部门中每个岗位的最高薪水select t.deptno, t.job, max(t.sal) avg_sal from emp t group by t.deptno, job ;
having
eg: 每个部门的平均薪水大于 2000 的部门select deptno, avg(sal) avg_sal from emp group by deptno having avg_sal > 2000;
=======================================
join
目前 hive 不支持 in
或not in
中包含查询子句的语法,所以只能通过 left join 实现。
1. 等值 jion
join … onselect e.empno, e.ename, d.deptno, d.dname from emp e join dept d on e.deptno = d.deptno ;
不支持 <> 等非等值连接方式。
2. 左连接
left joinselect e.empno, e.ename, d.deptno, d.dname from emp e left join dept d on e.deptno = d.deptno ;
3. 右连接
right joinselect e.empno, e.ename, e.deptno, d.dname from emp e right join dept d on e.deptno = d.deptno ;
4. 全连接
full joinselect e.empno, e.ename, e.deptno, d.dname from emp e full join dept d on e.deptno = d.deptno ;
5. 半连接 (LEFT SEMI JOIN)
是 hive 特有的,hive 中不支持 in/exists 操作,所以 hive 提供了一个替代方案。需要注意的是,被连接的表 (右表),不能出现在查询列 / 其他部分(where 等) 中,只能出现在 on 字句中 (出现也是无效的)。
提出半连接的主要作用其实是提高查询效率,真正来讲的话,hive 中可以使用其他连接方式来代替半连接,但是就效率而已的话,还是半连接比较高效。
语法格式:table_reference LEFT SEMI JOIN table_factor join_condition;
6. 多表连接
多表连接的时候,一般先进行 left semi join,然后再进行 join, 再进行外连接。(减少数据量)。
补充:
join 过滤条件,可以将 where 的过滤条件移动到 join 的过滤条件中去,这样可以减少网络数据量。
join 执行顺序都是从左到右,不管是那种 join 方式,那么一般 将大的表放到右边
,这样可以节省内存 & 减少网络传输。
如果所有被连接的表都是小表,那么可以使用 mapjoin, 将需要连接的表数据全部读入 mapper 端内存中。也就是说你使用 mapjoin 的前提就是你的连接数据比较小,mapjoin 需要和其他 join 方式一起使用,一般情况下使用 mapjoin 的时候,推荐使用内连接。语法格式为:select /*+ MAPJOIN(table_ref1) */ ... from table_ref join table_ref1 on ....;
mapjoin 只适合连接表是小表的情况,是一种空间换时间的解决方案。
order by
对全局数据的一个排序,仅仅只有 1 个 reduceselect * from emp order by empno desc ;
降序
sort by
对每一个 reduce 内部数据进行排序的,全局结果集来说不是排序
`set mapreduce.job.reduces= 3;
select * from emp sort by empno asc ;
insert overwrite local directory ‘/opt/datas/sortby-res’ select * from emp sort by empno asc ;`
distribute by
分区 partition,类似于 MapReduce 中分区 partition, 对数据进行分区,结合 sort by 进行使用(分区再排序)insert overwrite local directory '/opt/datas/distby-res' select * from emp distribute by deptno sort by empno asc ;
注意事项:distribute by
必须要在sort by
前面。
cluster by
当 distribute by 和 sort by 字段相同时,可以使用 cluster by ;insert overwrite local directory '/opt/datas/cluster-res' select * from emp cluster by empno ;
怎样预防全表扫描
1. 应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
2. 应尽量避免在 where 子句中使用!= 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫
3. 描应尽量避免在 where 子句中使用 or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描
4.in 和 not in,用具体的字段列表代替,不要返回用不到的任何字段。in 也要慎用,否则会导致全表扫描
5. 避免使用模糊查询
6. 任何地方都不要使用select* from t;
操作文件系统
dfs -rm -R /user/hive/warehouse/….;
删除 dfs -ls / ;
查看 hdfs 文件系统 !ls /opt/datas;
查看本地文件系统
HQL 语句转换成 MapReduce 作业的基本原理
https://blog.csdn.net/nameles…