Hive科普
Hive被设计用来进行大数据分析,可以让精通Sql的开发人员利用sql的方式处理分析大规模数据集。Hive构建在HDFS之上,Hive把数据组织成表存储在HDFS之上,而元数据(表结构)存储在metadata数据库(可以选择mysql作为实现)中。
简单示例
使用Hive查询气象数据集数据格式。
- 创建表结构
CREATE TABLE records(year String, temperature INT, quality INT)
ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t';
ROW FORMAT DELIMITED FIELDS TERMINATED BY ‘\t’ 是HiveQL所特有的,表示每行数据由制表符分隔,每行由三个字段,分别对应表中的三列,每行以换行符分隔。
2. 向Hive中输入数据
LOAD DATA LOCAL INPATH 'input/data/sample.txt'
OVERWRITE INTO TABLE records;
需要注意的是这只是一个普通的文件拷贝,应为Hive并不会处理数据结构,因为Hive并不强制使用特定格式的文件,结果就是导入的数据与原来的文件格式一致。
仓库的位置由hive.metastore.warehouse.dire指定,默认是/usr/hive/warehouse。
可以到该目录看到sample.txt文件。
OVERWRITE 表示删除表中原有数据文件。
3. 查询
SELECT year,MAX(temperature) FROM records
WHERE temperature != 9999 AND quality IN (0,1,4,5,9)
GROUP BY year;
Hive的优势在于将会把SQL转换为作业进行执行。
运行Hive
Hive配置
Hive使用xml作为配置文件,在conf目录下的hivesite.xml。hive-default.xml存储默认的配置选项。
传递–config选项参数给hive命令。通过这种方式可以重新定义hive查找hivesite.xml的目录。
Hive还允许使用-hiveconf选项来为单个会话设置属性,例如,下面的命令设定在会话中使用一个(伪分布)集群。
hive -hiveconf fs.defaultFS=hdfs://localhsot -hiveconf mapreduce.framework.name=yarn -hiveconf yarn.resourcemanager.address=localhost:8032
还可以在一个会话中使用SET命令临时更改设置。例如:
hive> SET hive.enforce.bucketing=true;
//只带属性名的SET可以查看任何属性的当前值
hive> SET hive.enforce.buckting;
hive.enforce.buckting=true
只带属性名的SET可以查看任何属性的当前值。但是并不会列出默认值,只会列出用户设置过的值。
SET -v命令可以列出所有的属性和当前值(包括默认的)。
属性设置的优先级高低(从高到低):
- Hive Set命令。
- 命令行-hiveconf选项。
- hive-site.xml和hadoop站点文件(core-site.xml hdfs-site.xml mapredsite.xml yarn-site.xml)
- hive默认值和hadoop默认文件(core-default.xml hdfs-defauld.xml mapred-default.xml yarn-default.xml)
执行引擎
默认的执行引擎是MapReduce(mr),另外还包括tez, spark。Tez和Spark都是DAG(有向无环图)引擎。使用MapReduce中间作业的输出会被物化存储到HDFS,Tez和Spark则不同,他们可以根据Hive规划器的请求,把中间结果写到本地磁盘上,甚至在内存中缓存,以避免额外的复制开销。
使用哪种引擎,由hive.execution.engine控制。默认值是mr(MapReduce)。
Hive服务
Hive支持以多种服务模式运行,主要有:
- cli Hive的命令行服务(Shell 环境)。这是默认的服务。
- hiveserver2 以提供Thrift服务的服务器来运行。允许用不同语言编写程序进行访问。使用Thrift客户端,JDBC客户端和ODBC客户,需要连接开启这个服务的Hive 。
- metastore 默认情况下,metastore和hive在同一个进程里运行。使用这个服务,可以让metastore作为一个单独的进行运行。
- hwi Hive的WEB接口。Hue是一个功能更全面的WEB接口。
客户端包括:
- thrift客户端。
- JDBC驱动,Hive提供了Type4(纯Java)的JDBC驱动,定义在org.apache.hadoop.hive.jdbc.HiveDriver类中。在以jdbc:hive2://host:port/dbname形式配置JDBC URI后,Java应用程序可以连接指定主机端口的hive服务(hiveserver2)。
Hive客户端与服务端以及通信方式:
Metastore
Metasotore是Hive元数据的集中存放地。metastore包括两部分:服务和后台数据存储。
- 默认情况下,metastore服务和hive服务在同一个JVM进程中运行,它包括一个内嵌的以本地磁盘作为存储的Derby数据块实例。
- 如果需要支持多个会话以及多个用户,需要使用一个独立的数据块。这种配置称为本地metastore配置。因为metastore服务仍然和hive服务运行在同一个进程中。但是数据库运行在另一个进程中或另一台机器上。任何支持JDBC的数据块都可以作为Hive的metastore。可以按照下图中的属性进行配置。例如配置Mysql为metastore实现。需要将Mysql的数据块驱动放到hive的lib中,配置相应的ConnectionURL ConnectionDriveName。
- 一个或多个metastore服务器和hive服务运行在不同的进程中。这样数据块层可以放置到防火墙后。这种称为远程metastore配置。hive连接远程metastore的URI的形式为thrift://host:port。
metastore数据配置属性:
metastore服务运行方式:
与传统数据块相比
读时模式VS写时模式
读时模式 | 写时模式 | |
---|---|---|
定义 | 在数据读取时验证数据格式,写入时不做验证 | 数据写入时验证数据格式,如果格式不满足不允许写入 |
优点 | 数据加载很快,因为不需要验证格式;数据可以有多种模式,更灵活,例如一套hdfs数据可以定义多种hive表 | 查询性能高 |
缺点 |
更新,事务,索引
hive适合批量数据分析(OLAP),这种场景下,普遍是全表扫描,所以对于索引,事务等支持的不是很完善。
自0.14.0版本开始,支持insert into table…values 操作,另外也支持update,delete操作。
hive不支持就地更新,所有的数据变化,都是通过metastore的MapReduce作业会定期将这些增量文件合并到"基表"文件中。而且只能在事务(0.13.0引入)的背景下才能发挥作用,因此这些使用的表必须启用了事务,以保证对这些表的读操作可以看到表的一致性快照。
0.7.0版本引入了表级锁和分区级锁。有了锁,就可以防止一个进程删除正在由另一个进程读取的表。锁由zk透明管理。因此用户不用执行获得和释放锁的操作,但是可以使用SHOW LOCKS 获取已经获得了哪些锁信息。默认情况下,并未启用锁功能。
SQL与HiveQL比较
hive的数据类型
托管表与外部表
hive中的表实际上由数据本身和描述数据的元数据组成,数据本身可以一般存放在hdfs中,当然也可以是其他任何hadoop文件系统,包括本地文件系统。元数据存放在关系型数据库中(metastore)。
默认情况下hive负责管理数据。意味着hive把数据移入他的仓库目录。另一种选择是创建一个外部表,这会让hive到仓库目录以外的地方访问数据。
例如:
1 创建托管表并加载hdfs上的数据
//托管表 hive会把数据移动到仓库目录
CREATE TABLE managed_table(dummy STRING);
LOAD DATA INPATH '/user/tom/data.txt' INTO table managed_table;
上面的命令会把hdfs://user/tom/data.txt移动到hive的managed_table的仓库目录hdfs://user/hive/warehourse/managed_table。
如果使用LOCAL关键字 hive会把本地文件系统的数据复制到hive的仓库目录。在其他情况下,最好把LOAD视为一个移动操作!!
2 创建外部表
//创建外部表
CREATE EXTERNAL TABLE erternal_table(dummy STRING)
LOCATION '/user/tom/erternal_table';
LOAD DATA INPATH '/user/tom/data.txt' INTO table erternal_table;
创建外部表时,hive不会检测外部路径是否存在,这意味着你可以在创建表之后再去创建外部数据。
分区和桶
hive把表组织成分区(partition)。这是一种根据分区列(partition column,如日期)的值对表进行粗略划分的机制。使用分区可以加快数据分片的查询速度。
表或分区可以进一步划分为桶(bucket)。例如可以根据用户id,这一列来创建桶。hive会取列的hash值然后mod桶的个数,决定数据存在在哪个桶中。这样可以用于随机取样,例如取所有数据集的1/2,就可以通过指定桶的条件来实现。而且桶还可以用于join操作,连接两个在相同列上划分了桶的表。
例子:
1 创建分区表,指定以时间(dt)和国家(country)分区。
CREATE TABLE logs(ts BIGINT , line STRING)
PARTITIONED BY (dt STRING, country STRING);
//加载数据时 需要指定分区值
LOAD DATA LOCAL INPATH 'input/hive/partition/file1'
INTO TABLE logs
PARTITION(dt='2001-01-01', country='CN') ;
//使用动态分区导入数据
INSERT OVERWRITE TABLE logs
PARTITION(dt)
SELECT ts, line, dt
FROM sourceTable;
分区之后目录结构将长下面这样:
要查看表上的分区,可以使用
show partitions logs 命令
注意:
PARTITIONED BY 子句中的列定义是表中正式的列,称为分区列,但是,数据文件并不包含这些列的值,因为他们源于目录名。
在查询时可以使用分区:
SELECT ts, dt, line
FROM logs
WHERE country = 'CN';
以上查询只会扫描country='CN’的分区。
另外查询会返回dt列(分区列),是hive从文件目录中提取的,因为在数据文件中并不包含。
2 使用桶的例子
//在id列上创建4个桶
CREATE TABLE buckteed_users(id INT, name STRING)
CLUSTERED BY (id) INTO 4 BUCKTES;
//划分桶 并让通中的数据排序
CREATE TABLE buckteed_users(id INT, name STRING)
CLUSTERED BY (id) SORTED BY (id ASC) INTO 4 BUCKTES;
//使用桶 获取1/4数据
SELECT * FROM buckteed_users
TABLESAMPLE(BUCKET 1 OUT OF 4 ON id);
//获取1/2数据
SELECT * FROM buckteed_users
TABLESAMPLE(BUCKET 1 OUT OF 2 ON id);
排序和聚集
ORDER BY 语句会对结果进行全集排序。有时并不需要,这时可以使用hive扩展的SORT BY,它为每个reducer产生一个排序文件。
例如:
排序每个年份中的温度
FROM records2
SELECT year, temperature
DISTRIBUTE BY year
SORT BY year ASC, temperature DESC;
以上查询如果SORT BY 和 DISTRIBUTE BY中用的列相同,可以缩写为CLUSTER BY。
使用mapreduce脚本
通过add来注册脚本,hive知道需要把脚本传输到hadoop集群上。
map reduce: