摘要: Hive灵活易用且易于维护,十分适合数据仓库的统计分析,什么样的结构让它具备这些特性?我们如何才能灵活操作hive呢?
博主福利
给大家推荐一套hadoop视频课程
[百度hadoop核心架构师,首次内部分享的企业级项目视频,价值3980元]
免费赠送100份,先到先得。联系老师微信windgs,备注OSchina。
部分视频截图展示
Hive
hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张数据库表,并提供完整的sql查询功能,Hive 定义了简单的类 SQL 查询语言,称为 HQL,它允许熟悉 SQL 的用户查询数据可以将 sql语句转换为MapReduce任务进行运行,不必开发专门的MapReduce。毕竟会写SQL的人比写JAVA的人多,这样可以让一大批运营人员直接获取海量数据。在数据仓库建设中,HIVE灵活易用且易于维护,十分适合数据仓库的统计分析。
本章内容:
1) Hive简介
2) Hive基础组成
3) Hive执行流程
4) Hive基础操作
1. Hive基础原理
hive是建设在Hadoop之上,Hive包括如下组件:CLI(command line interface)、JDBC/ODBC、Thrift Server、WEB GUI、MetaStore和Driver(Complier、Optimizer和Executor)。
1) Driver组件:包括Complier、Optimizer和Executor,它的作用是将我们写的HiveQL(类SQL)语句进行解析、编译优化,生成执行计划,然后调用底层的MapReduce计算框架。
2) Metastore组件:元数据服务组件存储hive的元数据,hive的元数据存储在关系数据库里,hive支持的关系数据库有derby、mysql。Hive还支持把metastore服务安装到远程的服务器集群里,从而解耦hive服务和metastore服务。
3) Thrift服务:thrift是facebook开发的一个软件框架,它用来进行可扩展且跨语言的服务的开发,hive集成了该服务,能让不同的编程语言调用hive的接口。
4) CLI:command line interface,命令行接口。
5) Thrift客户端: hive架构的许多客户端接口是建立在thrift客户端之上,包括JDBC和ODBC接口。
6) WEBGUI:hive客户端提供了一种通过网页的方式访问hive所提供的服务。
用户接口主要有三个:CLI,Client 和 WUI。其中最常用的是CLI,公司内可通过堡垒机连接ssh hdp_lbg_ectech@10.126.101.7,直接输入hive,就可连接到HiveServer。
Hive的metastore组件是hive元数据集中存放地。Metastore组件包括两个部分:metastore服务和后台数据的存储。后台数据存储的介质就是关系数据库,例如hive默认的嵌入式磁盘数据库derby,还有mysql数据库。Metastore服务是建立在后台数据存储介质之上,并且可以和hive服务进行交互的服务组件,默认情况下,metastore服务和hive服务是安装在一起的,运行在同一个进程当中。我也可以把metastore服务从hive服务里剥离出来,metastore独立安装在一个集群里,hive远程调用metastore服务,这样我们可以把元数据这一层放到防火墙之后,客户端访问hive服务,就可以连接到元数据这一层,从而提供了更好的管理性和安全保障。使用远程的metastore服务,可以让metastore服务和hive服务运行在不同的进程里,这样也保证了hive的稳定性,提升了hive服务的效率。
对于数据存储,Hive没有专门的数据存储格式,可以非常自由的组织Hive中的表,只需要在创建表的时候告诉Hive数据中的列分隔符和行分隔符,Hive就可以解析数据。Hive中所有的数据都存储在HDFS中,存储结构主要包括数据库、文件、表和视图。Hive中包含以下数据模型:Table内部表,External Table外部表,Partition分区,Bucket桶。Hive默认可以直接加载文本文件,还支持sequence file 、RCFile。
Hive的数据模型介绍如下:
1) Hive数据库
类似传统数据库的DataBase,例如 hive >create database test_database;
2) 内部表
Hive的内部表与数据库中的表在概念上是类似。每一个Table在Hive中都有一个相应的目录存储数据。例如一个表hive_test,它在HDFS中的路径为/home/hdp_lbg_ectech/warehouse/hdp_lbg_ectech_bdw.db/hive_test,其中/home/hdp_lbg_ectech/warehouse是在hive-site.xml中由${hive.metastore.warehouse.dir}指定的数据仓库的目录,所有的Table数据(不包括外部表)都保存在这个目录中。删除表时,元数据与数据都会被删除。
建表语句示例:
CREATE EXTERNAL TABLE hdp_lbg_ectech_bdw.hive_test
(`userid` string COMMENT'')
ROW FORMAT DELIMITED FIELDS TERMINATED BY'\001';
load data inpath ‘/home/hdp_lbg_ectech/resultdata/test.txt’overwrite into table hive_test;
3) 外部表
外部表指向已经在HDFS中存在的数据,可以创建分区。它和内部表在元数据的组织上是相同的,而实际数据的存储则有较大的差异。内部表在加载数据的过程中,实际数据会被移动到数据仓库目录中。删除表时,表中的数据和元数据将会被同时删除。而外部表只有一个过程,加载数据和创建表同时完成(CREATE EXTERNAL TABLE ……LOCATION),实际数据是存储在LOCATION后面指定的 HDFS 路径中,并不会移动到数据仓库目录中。当删除一个外部表时,仅删除该表的元数据,而实际外部目录的数据不会被删除,推荐使用这种模式。
4) 分区
Partition相当于数据库中的列的索引,但是Hive组织方式和数据库中的很不相同。在Hive中,表中的一个分区对应于表下的一个目录,所有的分区数据都存储在对应的目录中。
一般是按时间、地区、类目来分区,便于局部查询,避免扫描整个数据源。
5) 桶
Buckets是将表的列通过Hash算法进一步分解成不同的文件存储。它对指定列计算hash,根据hash值切分数据,目的是为了并行,每一个Bucket对应一个文件。例如将userid列分散至32个bucket,首先对userid列的值计算hash,对应hash值为0的HDFS目录为/home/hdp_lbg_ectech/resultdata/part-00000;hash值为20的HDFS目录为/home/hdp_lbg_ectech/resultdata/part-00020。
6) Hive的视图
视图与传统数据库的视图类似。目前只有逻辑视图,没有物化视图;视图只能查询,不能Load/Insert/Update/Delete数据;视图在创建时候,只是保存了一份元数据,当查询视图的时候,才开始执行视图对应的那些子查询;
2. Hive基础操作
1) DDL操作:包括
l 建表,删除表
l 修改表结构
l 创建/删除视图
l 创建数据库和显示命令
l 增加分区,删除分区
l 重命名表
l 修改列的名字、类型、位置、注释
l 增加/更新列
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name [(col_name data_type [COMMENT col_comment], ...)] [COMMENT table_comment] [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)] [CLUSTERED BY (col_name, col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS] [ROW FORMAT row_format] [STORED AS file_format] [LOCATION hdfs_path] |
l CREATE TABLE 创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXIST 选项来忽略这个异常
l EXTERNAL 关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION)
l LIKE 允许用户复制现有的表结构,但是不复制数据
l COMMENT可以为表与字段增加描述
l ROW FORMAT
DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char]
[MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char]
| SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
用户在建表的时候可以自定义 SerDe 或者使用自带的 SerDe。如果没有指定 ROW FORMAT 或者 ROW FORMAT DELIMITED,将会使用自带的 SerDe。在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的 SerDe,Hive 通过 SerDe 确定表的具体的列的数据。
l STORED AS
SEQUENCEFILE
| TEXTFILE
| RCFILE
| INPUTFORMAT input_format_classname OUTPUTFORMAT output_format_classname
如果文件数据是纯文本,可以使用 STORED AS TEXTFILE。如果数据需要压缩,使用 STORED AS SEQUENCE 。
例子1:创建简单表
CREATE TABLE pokes (foo INT, bar STRING); |
例子2:创建外部表
CREATE EXTERNAL TABLE page_view(viewTime INT, userid BIGINT, page_url STRING, referrer_url STRING, ip STRING COMMENT 'IP Address of the User', country STRING COMMENT 'country of origination') COMMENT 'This is the staging page view table' ROW FORMAT DELIMITED FIELDS TERMINATED BY '\054' STORED AS TEXTFILE LOCATION '<hdfs_location>'; |
例子3:创建分区表
CREATE TABLE par_table(viewTime INT, userid BIGINT, page_url STRING, referrer_url STRING, ip STRING COMMENT 'IP Address of the User') COMMENT 'This is the page view table' PARTITIONED BY(date STRING, pos STRING) ROW FORMAT DELIMITED ‘\t’ FIELDS TERMINATED BY '\n' STORED AS SEQUENCEFILE; |
例子4:创建Bucket表
CREATE TABLE par_table(viewTime INT, userid BIGINT, page_url STRING, referrer_url STRING, ip STRING COMMENT 'IP Address of the User') COMMENT 'This is the page view table' PARTITIONED BY(date STRING, pos STRING) CLUSTERED BY(userid) SORTED BY(viewTime) INTO 32 BUCKETS ROW FORMAT DELIMITED ‘\t’ FIELDS TERMINATED BY '\n' STORED AS SEQUENCEFILE; |
例子5:创建表并创建索引字段ds
CREATE TABLE invites (foo INT, bar STRING) PARTITIONED BY (ds STRING); |
例子6:复制一个空表
CREATE TABLE empty_key_value_store LIKE key_value_store; |
例子7:显示所有表
SHOW TABLES; |
例子8:按正则条件(正则表达式)显示表
SHOW TABLES '.*s'; |
例子9:表添加一列
ALTER TABLE pokes ADD COLUMNS (new_col INT); |
例子10:添加一列并增加列字段注释
ALTER TABLE invites ADD COLUMNS (new_col2 INT COMMENT 'a comment'); |
例子11:更改表名
ALTER TABLE events RENAME TO 3koobecaf; |
例子12:删除列
DROP TABLE pokes; |
例子13:增加、删除分区
增加: ALTER TABLE table_name ADD [IF NOT EXISTS] partition_spec [ LOCATION 'location1' ] partition_spec [ LOCATION 'location2' ] ... partition_spec: : PARTITION (partition_col = partition_col_value, partition_col = partiton_col_value, ...) 删除: ALTER TABLE table_name DROP partition_spec, partition_spec,... |
例子14:重命名表
ALTER TABLE table_name RENAME TO new_table_name |
例子15:修改列的名字、类型、位置、注释
ALTER TABLE table_name CHANGE [COLUMN] col_old_name col_new_name column_type [COMMENT col_comment] [FIRST|AFTER column_name] 这个命令可以允许改变列名、数据类型、注释、列位置或者它们的任意组合 |
例子16:创建/删除视图
CREATE VIEW [IF NOT EXISTS] view_name [ (column_name [COMMENT column_comment], ...) ][COMMENT view_comment][TBLPROPERTIES (property_name = property_value, ...)] AS SELECT 增加视图 如果没有提供表名,视图列的名字将由定义的SELECT表达式自动生成 如果修改基本表的属性,视图中不会体现,无效查询将会失败 视图是只读的,不能用LOAD/INSERT/ALTER
DROP VIEW view_name 删除视图 |
例子17:创建数据库
CREATE DATABASE name |
例子18:显示命令
show tables; show databases; show partitions ; show functions describe extended table_name dot col_name |
2) DML操作:元数据存储
hive不支持用insert语句一条一条的进行插入操作,也不支持update操作。数据是以load的方式加载到建立好的表中。数据一旦导入就不可以修改。
DML包括:
l INSERT插入
l UPDATE更新
l DELETE删除
l 向数据表内加载文件
l 将查询结果插入到Hive表中
LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 ...)]
Load 操作只是单纯的复制/移动操作,将数据文件移动到 Hive 表对应的位置。 filepath 相对路径,例如:project/data1 绝对路径,例如: /user/hive/project/data1 包含模式的完整 URI,例如:hdfs://namenode:9000/user/hive/project/data1 |
例子1:向数据表内加载文件
LOAD DATA LOCAL INPATH './examples/files/kv1.txt' OVERWRITE INTO TABLE pokes; |
例子2:加载本地数据,同时给定分区信息
LOAD DATA LOCAL INPATH './examples/files/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15'); |
例子3:加载本地数据,同时给定分区信息
LOAD DATA INPATH '/user/myname/kv2.txt' OVERWRITE INTO TABLE invites PARTITION (ds='2008-08-15'); |
例子4:将查询结果插入Hive表
基本模式: INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement
多插入模式: FROM from_statement INSERT OVERWRITE TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 [INSERT OVERWRITE TABLE tablename2 [PARTITION ...] select_statement2] ...
自动分区模式: INSERT OVERWRITE TABLE tablename PARTITION (partcol1[=val1], partcol2[=val2] ...) select_statement FROM from_statement |
例子3:将查询结果写入HDFS文件系统
INSERT OVERWRITE [LOCAL] DIRECTORY directory1 SELECT ... FROM ...
FROM from_statement INSERT OVERWRITE [LOCAL] DIRECTORY directory1 select_statement1 [INSERT OVERWRITE [LOCAL] DIRECTORY directory2 select_statement2]
数据写入文件系统时进行文本序列化,且每列用^A 来区分,\n换行 |
例子3:INSERT INTO
INSERT INTO TABLE tablename1 [PARTITION (partcol1=val1, partcol2=val2 ...)] select_statement1 FROM from_statement |
3) DQL操作:数据查询SQL
DQL包括:
l 基本的Select 操作
l 基于Partition的查询
l Join
基本Select操作:
SELECT [ALL | DISTINCT] select_expr, select_expr, ... FROM table_reference [WHERE where_condition] [GROUP BY col_list [HAVING condition]] [ CLUSTER BY col_list | [DISTRIBUTE BY col_list] [SORT BY| ORDER BY col_list] ] [LIMIT number]
l 使用ALL和DISTINCT选项区分对重复记录的处理。默认是ALL,表示查询所有记录。DISTINCT表示去掉重复的记录 l Where 条件 l 类似我们传统SQL的where 条件 l 目前支持 AND,OR ,0.9版本支持between l IN, NOT IN l 不支持EXIST ,NOT EXIST
ORDER BY与SORT BY的不同 l ORDER BY 全局排序,只有一个Reduce任务 l SORT BY 只在本机做排序
Limit l Limit 可以限制查询的记录数 |
例子1:按先件查询
SELECT a.foo FROM invites a WHERE a.ds='<DATE>'; |
例子2:将查询数据输出至目录
INSERT OVERWRITE DIRECTORY '/tmp/hdfs_out' SELECT a.* FROM invites a WHERE a.ds='<DATE>'; |
例子3:将查询结果输出至本地目录
INSERT OVERWRITE LOCAL DIRECTORY '/tmp/local_out' SELECT a.* FROM pokes a; |
例子4:选择所有列到本地目录
hive> INSERT OVERWRITE TABLE events SELECT a.* FROM profiles a; INSERT OVERWRITE TABLE events SELECT a.* FROM profiles a WHERE a.key < 100; INSERT OVERWRITE LOCAL DIRECTORY '/tmp/reg_3' SELECT a.* FROM events a; INSERT OVERWRITE DIRECTORY '/tmp/reg_4' select a.invites, a.pokes FROM profiles a; INSERT OVERWRITE DIRECTORY '/tmp/reg_5' SELECT COUNT(1) FROM invites a WHERE a.ds='<DATE>'; INSERT OVERWRITE DIRECTORY '/tmp/reg_5' SELECT a.foo, a.bar FROM invites a; INSERT OVERWRITE LOCAL DIRECTORY '/tmp/sum' SELECT SUM(a.pc) FROM pc1 a; |
例子5:将一个表的统计结果插入另一个表中
INSERT OVERWRITE TABLE events SELECT a.bar, count(1) FROM invites a WHERE a.foo > 0 GROUP BY a.bar; FROM pokes t1 JOIN invites t2 ON (t1.bar = t2.bar) INSERT OVERWRITE TABLE events SELECT t1.bar, t1.foo, t2.foo; |
例子6:将多表数据插入到同一表中
FROM src INSERT OVERWRITE TABLE dest1 SELECT src.* WHERE src.key < 100 INSERT OVERWRITE TABLE dest2 SELECT src.key, src.value WHERE src.key >= 100 and src.key < 200 INSERT OVERWRITE TABLE dest3 PARTITION(ds='2008-04-08', hr='12') SELECT src.key WHERE src.key >= 200 and src.key < 300 INSERT OVERWRITE LOCAL DIRECTORY '/tmp/dest4.out' SELECT src.value WHERE src.key >= 300; |
例子7:将文件流直接插入文件
FROM invites a INSERT OVERWRITE TABLE events SELECT TRANSFORM(a.foo, a.bar) AS (oof, rab) USING '/bin/cat' WHERE a.ds > '2008-08-09'; |
在Hadoop生态圈中,针对大数据进行批量计算时,通常需要一个或者多个MapReduce作业来完成,但这种批量计算方式是满足不了对实时性要求高的场景。
此时就到了Storm上场的时候,那Storm又是如何高效完成实时计算的呢?下一篇我会介绍开源分布式实时计算系统——Storm。