apache hive 使用概述

1         产品概述

1.1  产品功能

        Apache Hive数据仓库软件提供对存储在分布式中的大型数据集的查询和管理,它自己是创建在Apache Hadoop之上,主要提供如下功能:java

1. 它提供了一系列的工具,可用来对数据进行提取/转化/加载(ETL);是一种能够存储、查询和分析存储在HDFS(或者HBase)中的大规模数据的机制;查询是经过MapReduce来完成的(并非全部的查询都须要MapReduce来完成,好比select * from XXX就不须要;在Hive0.11对相似select a,b from XXX的查询经过配置也能够不经过MapReduce来完成);node

2. Hive是一种创建在Hadoop文件系统上的数据仓库架构,并对存储在HDFS中的数据进行分析和管理;mysql

3. Hive定义了一种相似SQL的查询语言,被称为HQL,对于熟悉SQL的用户能够直接利用Hive来查询数据。同时,这个语言也容许熟悉MapReduce开发者们开发自定义的mappersreducers来处理内建的mappersreducers没法完成的复杂的分析工做。Hive能够容许用户编写本身定义的函数UDF,在查询中使用。Hive中有3UDFUser Defined FunctionsUDF)、User Defined Aggregation FunctionsUDAF)、User Defined Table Generating FunctionsUDTF)。web

    如今,Hive已是一个成功的Apache项目,不少组织把它用做一个通用的、可伸缩的数据处理平台。sql

        Hive和传统的关系型数据库有很大的区别,Hive将外部的任务解析成一个MapReduce可执行计划,而启动MapReduce是一个高延迟的一件事,每次提交任务和执行任务都须要消耗不少时间,这也就决定Hive只能处理一些高延迟的应用(若是想处理低延迟的应用,能够考虑一下Hbase)。同时,因为设计的目标不同,Hive目前还不支持事务;不能对表数据进行修改。shell

1.2  Hive和传统数据库进行比较

        Hive在不少方面和RMDB相似,好比说它支持SQL接口;可是因为其它底层设计的缘由,对HDFSMapreduce有很强的依赖,这也就意味这Hive的体系结构和RMDB有很大的区别。这些区别又间接的影响到Hive所支持的一些特性。数据库

    在传统的RMDB中,表的模式是在数据加载的时候强行肯定好的。若是在加载时发现数据不符合模式,则拒绝加载这些数据。而Hive在加载的过程当中不对数据进行任何的验证操做,其只是简单的将数据复制或者移动到表对应的目录下面。从这方面来讲,传统数据库在数据加载的过程当中比Hive要慢。可是由于传统数据库在数据加载过程当中能够进行一些处理,好比对某一列创建索引等,这样能够提高数据的查询性能。而在这方面Hive不行。express

比较项apache

SQLvim

HiveQL

ANSI SQL

支持

不彻底支持

更新

UPDATE\INSERT\DELETE

insert OVERWRITE\INTO TABLE

事务

支持

不支持

模式

写模式

读模式

数据保存

块设备、本地文件系统

HDFS

延时

多表插入

不支持

支持

子查询

彻底支持

只能用在From子句中

视图

Updatable

Read-only

可扩展性

数据规模

……

……

……

    从上表能够看出,Hive和传统的数据库仍是有不少的区别。

        HiveSQL方言通常被称为HiveQL,在下文咱们简称HQL。在上面咱们提到,HQL并不彻底支持SQL92标准。这个也是有缘由的。遵循SQL92Hive的设计开始就不是它的目标。

1.3 应用场景

        Hive目前主要应用在海量数据处理、数据挖掘、数据分析等方面,hive是针批量对长时间数据分析设计的,不能作交互式的实时查询。

2         产品架构

        Hive产品架构以下所示:

        Hive架构图中涉及服务、元数据、HdfsMapreduce等信息,下面分别进行说明:

2.1  服务

        hive有三种service,分别是clihiveserverhwi

1. cli是命令行工具,为默认服务,启动方式$HIVE_HOME/bin/hive $HIVE_HOME/bin/hive --service cli

2. hiverserver经过thrift对外提供服务,默认端口10000,启动方式为$HIVE_HOME/bin/hive--service hiveserver

3. hwiweb接口,能够经过浏览器访问hive,默认端口9999,启动方式为$HIVE_HOME/bin/hive--service hwi

    每一个服务间互相独立,有各自的配置文件(配置metasotre/namenode/jobtracker),若是metasotre的配置同样则物理上对应同一hive库。

        Driver用于解释、编译、优化、执行HQL,每一个serviceDriver相互独立。

        CLI为用户提供命令行接口,每一个CLI独享配置,即在一个CLI里修改配置不影响别的CLI

多个JDBC可同时连到同一HiveServer上,全部会话共享一份配置。(:0.9.0hiveserver配置已经从global降为session,即每一个session的配置相互独立)

     多个浏览器可同时连到同一HWI上,全部会话共享一份配置。

        Hive能够在运行时用–service选项来明确指定使用的服务类型,能够用下面的--service help来查看帮助,以下:

[wyp@master ~]$ hive --service help

Usage ./hive <parameters> --service serviceName <service parameters>

Service List: beeline cli help hiveserver2 hiveserver hwi jar lineage metastore metatool orcfiledump rcfilecat

Parameters parsed:

  --auxpath : Auxillary jars

  --config : Hive configuration directory

  --service : Starts specific service/component. cli is default

Parameters used:

  HADOOP_HOME or HADOOP_PREFIX : Hadoop install directory

  HIVE_OPT : Hive options

For help on a particular service:

  ./hive --service serviceName --help

Debug help:  ./hive --debug –help

    上面的输出项Service List,里面显示出Hive支持的服务列表:beeline cli help hiveserver2 hiveserver hwi jar lineage metastore metatool orcfiledump rcfilecat,下面介绍最经常使用的一些服务。

1cli:这个就是Command Line Interface的简写,是Hive的命令行界面,用的比较多。这是默认的服务,直接能够在命令行里面使用。

2hiveserver:这个可让Hive以提供Trift服务的服务器形式来运行,容许许多不一样语言编写的客户端进行通讯。使用时须要启动HiveServer服务以和客户端联系,能够经过设置HIVE_PORT环境变量来设置服务器所监听的端口号,在默认的状况下,端口为10000。能够经过下面方式来启动hiveserver

[wyp@master ~]$  bin/hive --service hiveserver -p 10002

Starting Hive Thrift Server

其中-p参数也是用来指定监听端口的。

3hwi:其实就是hive web interface的缩写,它是HiveWeb接口,是hive cli的一个web替换方案。

4jar:与Hadoop jar等价的Hive的接口,这是运行类路径中同时包含HadoopHive类的Java应用程序的简便方式。

5metastore:在默认状况下,metastoreHive服务运行在同一个进程中。使用这个服务,可让metastore做为一个单独的进程运行,能够经过METASTORE_PORT来指定监听的端口号,具体以下所示:

2.2  元数据

        Hive的数据分为表数据和元数据,表数据是Hive中表格(table)具备的数据;而元数据是用来存储表的名字,表的列和分区及其属性(是否为外部表等),表的数据所在目录等。

    元数据位置经过参数javax.jdo.option.ConnectionURL来指定,可在会话中自由修改。相关的参数包括:

javax.jdo.option.ConnectionDriverName           #数据库驱动

javax.jdo.option.ConnectionURL                      #数据库ip端口库名等

javax.jdo.option.ConnectionUserName              #用户名

javax.jdo.option.ConnectionPassword               #密码

经过修改这些参数能够在多个MetaStore间热切换,可用于HA

2.3  NameNodeJobTracker

        NameNodefs.default.name指定,JobTrackermapred.job.tracker指定,这两个参数均可以在会话中自由修改来指向不一样的NameNodeJobTracker

    配合MetaStore能够有多种组合出现,例如在同一个MetaStore里让table1的数据存在HDFS1,用JobTracker1计算,table2的数据存在HDFS2,用JobTracker2计算,或者让两个表都在JobTracker3上计算。

        NameNodeJobTracker最好指向同一个集群,不然计算的时候须要跨集群复制数据。

    在MetaStore存储的是表数据文件的绝对路径,小心其与NameNode/ JobTracker不在同一个集群里致使跨集群复制。

    对hiveserverhwi配置的修改会做用到同一service上的全部会话。(:0.9.0hiveserver配置已经从global降为session,即每一个session的配置相互独立)

3         安装部署

        Hive最新版本是apache-hive-0.13.1-bin.tar.gz,下载地址为http://apache.fayea.com/apache-mirror/hive/hive-0.13.1/

    下载后,选个目录,解压,命令以下:

# tar -zxvf hive-0.10.0.tar.gz

    如今须要配置Hive,才可以运行Hive。进入conf文件夹,将hive-default.xml.template文件的内容复制到hive-site.xml文件中,操做以下:

#cd conf/

#cp hive-default.xml.template hive-site.xml

    在hive-site.xml文件中进行以下配置:

<property>

<name>hive.metastore.warehouse.dir</name>

<value>/home/wyp/cloud/hive/warehouse</value>

<description>location of default database for the warehouse</description>

</property>

<property>

<name>javax.jdo.option.ConnectionURL</name>

<value>jdbc:mysql://localhost:3306/hive_hdp?characterEncoding=UTF-8&amp;createDatabaseIfNotExist=true</value>

<description>JDBC connect string for a JDBC metastore</description>

</property>

<property>

<name>javax.jdo.option.ConnectionDriverName</name>

<value>com.mysql.jdbc.Driver</value>

<description>Driver class name for a JDBC metastore</description>

</property>

<property>

<name>javax.jdo.option.ConnectionUserName</name>

<value>root</value>

<description>username to use against metastore database</description>

</property>

<property>

<name>javax.jdo.option.ConnectionPassword</name>

<value>123456</value>

<description>password to use against metastore database</description>

</property>

        Hive将元数据存储在RDBMS中,好比MySQLDerby中。Hive默认是用Derby数据库,这里修改成MySQL(因此要确保电脑上已经安装好了MySQL数据库)。须要将mysql驱动jarmysql-connector-java-5.1.22-bin.jar拷贝到$HIVE_HOME/lib/目录下。而后编辑/etc/profile文件,将Hivehome目录添加进去,操做以下:

#sudo vim /etc/profile

    在其中添加下面语句,修改Hivehome路径为解压的目录:

export HIVE_HOME=/home/...hive-0.10.0

PATH=$PATH:$HIVE_HOME/bin

    最后让上面的修改生效,请运行下面的命令:

#source /etc/profile

    如今能够试一下,hive是否安装好(须要启动Hadoop,不然不能运行成功!):

#hive

hive>

    若是出现了上述状况,说明hive安装成功。

4         数据存储模式

1. Hive的数据存储

        Hive是基于Hadoop分布式文件系统的,它的数据存储在Hadoop分布式文件系统中。Hive自己是没有专门的数据存储格式,也没有为数据创建索引,只须要在建立表的时候告诉Hive数据中的列分隔符和行分隔符,Hive就能够解析数据。因此往Hive表里面导入数据只是简单的将数据移动到表所在的目录中(若是数据是在HDFS上;但若是数据是在本地文件系统中,那么是将数据复制到表所在的目录中)。

        Hive中主要包含如下几种数据模型:Table(表),External Table(外部表),Partition(分区),Bucket(桶)。

a. 表:Hive中的表和关系型数据库中的表在概念上很相似,每一个表在HDFS中都有相应的目录用来存储表的数据,这个目录能够经过${HIVE_HOME}/conf/hive-site.xml配置文件中的hive.metastore.warehouse.dir属性来配置,这个属性默认的值是/user/hive/warehouse(这个目录在HDFS上),咱们能够根据实际的状况来修改这个配置。若是我有一个表wyp,那么在HDFS中会建立/user/hive/warehouse/wyp目录(这里假定hive.metastore.warehouse.dir配置为/user/hive/warehouse);wyp表全部的数据都存放在这个目录中。这个例外是外部表。

b.外部表:Hive中的外部表和表很相似,可是其数据不是放在本身表所属的目录中,而是存放到别处,这样的好处是若是你要删除这个外部表,该外部表所指向的数据是不会被删除的,它只会删除外部表对应的元数据;而若是你要删除表,该表对应的全部数据包括元数据都会被删除。

c.分区:在Hive中,表的每个分区对应表下的相应目录,全部分区的数据都是存储在对应的目录中。好比wyp表有dtcity两个分区,则对应dt=20131218,city=BJ对应表的目录为/user/hive/warehouse/dt=20131218/city=BJ,全部属于这个分区的数据都存放在这个目录中。

d.桶:对指定的列计算其hash,根据hash值切分数据,目的是为了并行,每个桶对应一个文件(注意和分区的区别)。好比将wypid列分散至16个桶中,首先对id列的值计算hash,对应hash值为016的数据存储的HDFS目录为:/user/hive/warehouse/wyp/part-00000;而hash值为2的数据存储的HDFS 目录为:/user/hive/warehouse/wyp/part-00002

Hive数据抽象结构以下所示:


2.Hive的元数据

        Hive中的元数据包括表的名字,表的列和分区及其属性,表的属性(是否为外部表等),表的数据所在目录等。因为Hive的元数据须要不断的更新、修改,而HDFS系统中的文件是多读少改的,这显然不能将Hive的元数据存储在HDFS中。目前Hive将元数据存储在数据库中,如MysqlDerby中。咱们能够经过如下的配置来修改Hive元数据的存储方式。

<property>

<name>javax.jdo.option.ConnectionURL</name>

<value>jdbc:mysql://localhost:3306/hive_hdp?characterEncoding=UTF-8

&createDatabaseIfNotExist=true</value>

<description>JDBC connect string for a JDBC metastore</description>

</property>

<property>

<name>javax.jdo.option.ConnectionDriverName</name>

<value>com.mysql.jdbc.Driver</value>

<description>Driver class name for a JDBC metastore</description>

</property>

<property>

<name>javax.jdo.option.ConnectionUserName</name>

<value>root</value>

<description>username to use against metastore database</description>

</property>

<property>

<name>javax.jdo.option.ConnectionPassword</name>

<value>123456</value>

<description>password to use against metastore database</description>

</property>

    还须要将链接对应数据库的依赖包复制到${HIVE_HOME}/lib目录中,这样才能将元数据存储在对应的数据库中。

5        基本操做

5.1  Hive内置数据类型

        Hive的内置数据类型能够分为两大类:(1)基础数据类型;(2)复杂数据类型。其中,基础数据类型包括:TINYINTSMALLINTINTBIGINTBOOLEANFLOATDOUBLESTRINGBINARYTIMESTAMPDECIMALCHARVARCHARDATE。下面的表格列出这些基础类型所占的字节以及从什么版本开始支持这些类型。

数据类型

所占字节

开始支持版本

TINYINT

1byte-128 ~ 127


SMALLINT

2byte-32,768 ~ 32,767 


INT

4byte,-2,147,483,648 ~   2,147,483,647


BIGINT

8byte,-9,223,372,036,854,775,808   ~ 9,223,372,036,854,775,807


BOOLEAN



FLOAT

4byte双精度


DOUBLE

8byte双精度


STRING



BINARY


Hive0.8.0开始支持

TIMESTAMP


Hive0.8.0开始支持

DECIMAL


Hive0.11.0开始支持

CHAR


Hive0.13.0开始支持

VARCHAR


Hive0.12.0开始支持

DATE


Hive0.12.0开始支持

复杂类型包括ARRAY,MAP,STRUCT,UNION,这些复杂类型是由基础类型组成的。

ARRAYARRAY类型是由一系列相同数据类型的元素组成,这些元素能够经过下标来访问。好比有一个ARRAY类型的变量fruits,它是由['apple','orange','mango']组成,那么咱们能够经过fruits[1]来访问元素orange,由于ARRAY类型的下标是从0开始的;

MAPMAP包含key->value键值对,能够经过key来访问元素。好比”userlist”是一个map类型,其中usernamekeypasswordvalue;那么咱们能够经过userlist['username']来获得这个用户对应的password

STRUCTSTRUCT能够包含不一样数据类型的元素。这些元素能够经过点语法的方式来获得所须要的元素,好比user是一个STRUCT类型,那么能够经过user.address获得这个用户的地址。

UNION: UNIONTYPE,他是从Hive 0.7.0开始支持的。

建立一个包含复制类型的表格能够以下:

CREATE TABLE employees (

    name STRING,

    salary FLOAT,

    subordinates ARRAY<STRING>,

    deductions MAP<STRING, FLOAT>,

    address STRUCT<street:STRING, city:STRING, state:STRING, zip:INT>

) PARTITIONED BY (country STRING, state STRING);

5.2  Hive参数配置方法

        Hive提供三种能够改变环境变量的方法,分别是:(1)修改${HIVE_HOME}/conf/hive-site.xml配置文件;(2)命令行参数;(3)在已经进入cli时进行参数声明。下面分别介绍这几种设定。

方法一:

    在Hive中,全部的默认配置都在${HIVE_HOME}/conf/hive-default.xml文件中,若是须要对默认的配置进行修改,能够建立一个hive-site.xml文件,放在${HIVE_HOME}/conf目录下。里面能够对一些配置进行个性化设定。在hive-site.xml的格式以下:

<configuration>

    <property>

        <name>hive.metastore.warehouse.dir</name>

        <value>/user/hive/warehouse</value>

        <description>location of

              default database for the warehouse</description>

    </property>

</configuration>

    全部的配置都是放在<configuration></configuration>标签之间,一个configuration标签里面能够存在多个<property></property>标签。<name>标签里面就是要设定属性的名称;<value>标签里面是要设定的值;<description>标签描述这个属性的做用。绝大多少配置都是在xml文件里面配置的,由于在这里作的配置都全局用户都生效,并且是永久的。用户自定义配置会覆盖默认配置。另外,Hive也会读入Hadoop的配置,由于Hive是做为Hadoop的客户端启动的,Hive的配置会覆盖Hadoop的配置。

方法二:

    在启动Hive cli的时候进行配置,能够在命令行添加-hiveconf param=value来设定参数,例如:

# hive --hiveconf mapreduce.job.queuename=queue1

    这样在Hive中全部MapReduce做业都提交到队列queue1中。这一设定对本次启动的会话有效,下次启动须要从新配置。

方法三:

    在已经进入cli时进行参数声明,能够在HQL中使用SET关键字设定参数,例如:

hive> set mapreduce.job.queuename=queue1;

    这样也能达到方法二的效果。这种配置也是对本次启动的会话有效,下次启动须要从新配置。在HQL中使用SET关键字还能够查看配置的值,以下:

hive> set mapreduce.job.queuename;

mapreduce.job.queuename=queue1

    咱们能够获得mapreduce.job.queuename=queue1。若是set后面什么都不添加,这样能够查到Hive的全部属性配置,以下:

hive> set;

datanucleus.autoCreateSchema=true

上述三种设定方式的优先级依次递增。即参数声明覆盖命令行参数,命令行参数覆盖配置文件设定。

5.3  Hive日志调试

    在不少程序中,能够经过输出日志的形式来获得程序的运行状况,经过这些输出日志来调试程序。

    在Hive中,使用的是Log4j来输出日志,默认状况下,CLI是不能将日志信息输出到控制台的。在Hive0.13.0以前版本,默认的日志级别是WARN,从Hive0.13.0开始,默认的日志级别是INFO。默认的日志存放在/tmp/<user.name>文件夹的hive.log文件中,即/tmp/<user.name>/hive.log

    在默认的日志级别状况下,不能将DEBUG信息输出,这样一来出现的各类详细的错误信息是不能输出的。可是能够经过如下两种方式修改log4j输出的日志级别,从而利用这些调试日志进行错误定位,具体作法以下:

# hive --hiveconf hive.root.logger=DEBUG,console

    或者在${HIVE_HOME}/conf/hive-log4j.properties文件中找到hive.root.logger属性,并将其修改成下面的设置

hive.root.logger=DEBUG,console

    上面两种方法的设置各有优劣,方法一的设定只是对本次会话有效,下次若是还想修改日志输出级别须要从新设定,可是不是每时每刻都须要修改日志的输出级别,因此在有时须要修改输出的日志级别,有时不须要的时候能够用这种方法;方法二将日志输出级别设定到文件中去了,这个设定是对全部的用户都生效,并且每次使用HQL的时候都会输出一大堆的日志,这种状况适合那些无时无刻都须要HQL的运行日志的用户。

5.4  hiveQL插入语法

1. Insert基本语法格式为:

INSERT OVERWRITE TABLE tablename [PARTITON(partcol1=val1,partclo2=val2)]select_statement FROM from_statement

示例:insert overwrite table test_insert select * from test_table;

2. 对多个表进行插入操做:

FROM fromstatte

INSERT OVERWRITE TABLE tablename1 [PARTITON(partcol1=val1,partclo2=val2)]select_statement1

INSERT OVERWRITE TABLE tablename2 [PARTITON(partcol1=val1,partclo2=val2)]select_statement2

示例:

from test_table

insert overwrite table test_insert1

select key

insert overwrite table test_insert2

select value;

insert的时候,from子句便可以放在select子句后面,也能够放在 insert子句前面。

hive不支持用insert语句一条一条的进行插入操做,也不支持update操做。数据是以load的方式加载到创建好的表中。数据一旦导入就不能够修改。

3.经过查询将数据保存到filesystem

INSERT OVERWRITE [LOCAL] DIRECTORY directory SELECT.... FROM .....

导入数据到本地目录:

insert overwrite local directory '/home/zhangxin/hive' select * from test_insert1;

产生的文件会覆盖指定目录中的其余文件,即将目录中已经存在的文件进行删除。

导出数据到HDFS中:

insert overwrite directory '/user/zhangxin/export_test' select value from test_table;

同一个查询结果能够同时插入到多个表或者多个目录中:

from test_insert1

insert overwrite local directory '/home/zhangxin/hive' select *

insert overwrite directory '/user/zhangxin/export_test' select value;

Hive insert into语句的标准语法以下:

用法一:

INSERT OVERWRITE TABLE tablename1 [PARTITION \

(partcol1=val1, partcol2=val2 ...) [IF NOT EXISTS]] \

select_statement1 FROM from_statement;

用法二:

INSERT INTO TABLE tablename1 [PARTITION \

(partcol1=val1, partcol2=val2 ...)] \

select_statement1 FROM from_statement;

举例:

hive> insert into table cite

> select * from tt;

    这样就会将tt表格里面的数据追加到cite表格里面。而且在cite数据存放目录生成了一个新的数据文件,这个新文件是通过处理的,列之间的分割是cite表格的列分割符,而不是tt表格列的分隔符。

(1) 若是两个表格的维度不同,将会插入错误:

hive> insert into table cite

> select * from cite_standby;

FAILED: SemanticException [Error 10044]: Line 1:18 Cannot insert into

target table because column number/types are different 'cite':

Table insclause-0 has 2 columns, but query has 1 columns.

    从上面错误提示看出,查询的表格cite_standby只有一列,而目标表格(也就是须要插入数据的表格)有2列,因为列的数目不同,致使了上面的语句不能成功运行,咱们须要保证查询结果列的数目和须要插入数据表格的列数目一致,这样才行。

(2) 在用extended关键字建立的表格上插入数据将会影响到其它的表格的数据,由于他们共享一份数据文件。

(3) 若是查询出来的数据类型和插入表格对应的列数据类型不一致,将会进行转换,可是不能保证转换必定成功,好比若是查询出来的数据类型为int,插入表格对应的列类型为string,能够经过转换将int类型转换为string类型;可是若是查询出来的数据类型为string,插入表格对应的列类型为int,转换过程可能出现错误,由于字母就不能够转换为int,转换失败的数据将会为NULL

(4) 能够将一个表查询出来的数据插入到原表中:

hive> insert into table cite

> select * from cite;

结果就是至关于复制了一份cite表格中的数据。

(5) insert overwrite的区别:

hive> insert overwrite table cite

> select * from tt;

上面的语句将会用tt表格查询到的数据覆盖cite表格已经存在的数据。

5.5  hiveQL删除语法

hiveQL删除语法以下所示:

hive> TRUNCATE TABLE t;

这样将会删掉表格t关联的全部数据,但会保留表和metadata的完整性。

5.6  hiveQL执行文件

Hive能够运行保存在文件里面的一条或多条的语句,只要用-f参数,通常状况下,保存这些Hive查询语句的文件一般用.q或者.hql后缀名,可是这不是必须的,你也能够保存你想要的后缀名。假设test文件里面有一下的Hive查询语句:

select * from p limit 10;

select count(*) from p;

那么咱们能够用下面的命令来查询:

#bin/hive -f test

........这里省略了一些输出...........

OK

196 242 3   881250949   20131102    jx

186 302 3   891717742   20131102    jx

22  377 1   878887116   20131102    jx

244 51  2   880606923   20131102    jx

Time taken: 4.386 seconds, Fetched: 4 row(s)

........这里省略了一些输出...........

OK

4

Time taken: 16.284 seconds, Fetched: 1 row(s)

若是你配置好了Hive shell的路径,你能够用SOURCE命令来运行那个查询文件:

[wyp@wyp hive-0.11.0-bin]$ hive

hive> source /home/.../test;

........这里省略了一些输出...........

........这里省略了一些输出...........

OK

196 242 3   881250949   20131102    jx

186 302 3   891717742   20131102    jx

22  377 1   878887116   20131102    jx

244 51  2   880606923   20131102    jx

Time taken: 4.386 seconds, Fetched: 4 row(s)

........这里省略了一些输出...........

OK

4

Time taken: 16.284 seconds, Fetched: 1 row(s)

6         数据导入导出

6.1  Hive数据导入的方式

Hive目前有四种导入数据的方式:

1)从本地文件系统中导入数据到Hive表;

2)从HDFS上导入数据到Hive表;

3)从别的表中查询出相应的数据并导入到Hive表中;

4)在建立表的时候经过从别的表中查询出相应的记录并插入到所建立的表中。

6.1.1            本地导入

先在Hive中建表,以下:

hive> create table wyp

     > (id  int , name string,

     > age  int , tel string)

     > ROW FORMAT DELIMITED

     > FIELDS TERMINATED BY '\t'

     > STORED AS TEXTFILE;

OK

Time taken:  2.832   seconds

这个表很简单,只有四个字段。本地文件系统中有个/home/wyp/wyp.txt文件,内容以下:

[wyp @master   ~]$ cat wyp.txt

1    wyp              25   13188888888888

2    test 30   13888888888888

3    zs    34   899314121

wyp.txt文件中的数据列之间是使用\t分割的,能够经过下面的语句将这个文件里面的数据导入到wyp表里面,操做以下:

hive> load data local inpath  'wyp.txt'   into table wyp;

Copying data from file:/home/wyp/wyp.txt

Copying file: file:/home/wyp/wyp.txt

Loading data to table  default .wyp

Table  default .wyp stats:

[num_partitions:  0 , num_files:  1 , num_rows:  0 , total_size:  67 ]

OK

Time taken:  5.967   seconds

这样就将wyp.txt里面的内容导入到wyp表里面去了,能够到wyp表的数据目录下查看,以下命令:

hive> dfs -ls /user/hive/warehouse/wyp ;

Found  1   items

-rw-r--r-- 3   wyp supergroup  67   2014 - 02 - 19   18 : 23   /hive/warehouse/wyp/wyp.txt

数据的确导入到wyp表里面去了。

和关系型数据库不同,Hive如今还不支持在insert语句里面直接给出一组记录的文字形式,也就是说,Hive并不支持INSERT INTO .... VALUES形式的语句。

6.1.2            HDFS导入

从本地文件系统中将数据导入到Hive表的过程当中,实际上是先将数据临时复制到HDFS的一个目录下(典型的状况是复制到上传用户的HDFS home目录下,好比/home/wyp/),而后再将数据从那个临时目录下移动(注意,这里说的是移动,不是复制!)到对应的Hive表的数据目录里面。既然如此,那么Hive确定支持将数据直接从HDFS上的一个目录移动到相应Hive表的数据目录下,假设有下面这个文件/home/wyp/add.txt,具体的操做以下:

[wyp@master /home/q/hadoop-2.2.0]$ bin/hadoop fs -cat /home/wyp/add.txt

5       wyp1    23      131212121212

6       wyp2    24      134535353535

7       wyp3    25      132453535353

8       wyp4    26      154243434355

上面是须要插入数据的内容,这个文件是存放在HDFS/home/wyp目录(和本地导入的不一样,本地导入中提到的文件是存放在本地文件系统上)里面,能够经过下面的命令将这个文件里面的内容导入到Hive表中,具体操做以下:

hive> load data inpath '/home/wyp/add.txt' into table wyp;

Loading data to table default.wyp

Table default.wyp stats:

[num_partitions: 0, num_files: 2, num_rows: 0, total_size: 215]

OK

Time taken: 0.47 seconds

 

hive> select * from wyp;

OK

5       wyp1    23      131212121212

6       wyp2    24      134535353535

7       wyp3    25      132453535353

8       wyp4    26      154243434355

1       wyp     25      13188888888888

2       test    30      13888888888888

3       zs      34      899314121

Time taken: 0.096 seconds, Fetched: 7 row(s)

从上面的执行结果能够看到,数据的确导入到wyp表中了!请注意load data inpath /home/wyp/add.txt into table wyp;里面是没有local这个单词的,这个是和本地导入方式的区别。

6.1.3            别的表查询导入

假设Hive中有test表,其建表语句以下所示:

hive> create table test(

    > id int, name string

    > ,tel string)

    > partitioned by

    > (age int)

    > ROW FORMAT DELIMITED

    > FIELDS TERMINATED BY '\t'

    > STORED AS TEXTFILE;

OK

Time taken: 0.261 seconds

大致和wyp表的建表语句相似,只不过test表里面用age做为了分区字段。下面语句将wyp表中的查询结果插入到test表中:

hive> insert into table test

    > partition (age='25')

    > select id, name, tel

    > from wyp;

#################################################################

           这里输出了一堆Mapreduce任务信息,这里省略

#################################################################

Total MapReduce CPU Time Spent: 1 seconds 310 msec

OK

Time taken: 19.125 seconds

hive> select * from test;

OK

5       wyp1    131212121212    25

6       wyp2    134535353535    25

7       wyp3    132453535353    25

8       wyp4    154243434355    25

1       wyp     13188888888888  25

2       test    13888888888888  25

3       zs      899314121       25

Time taken: 0.126 seconds, Fetched: 7 row(s)

经过上面的输出,咱们能够看到从wyp表中查询出来的东西已经成功插入到test表中去了!若是目标表(test)中不存在分区字段,能够去掉partition (age=25)语句。固然,也能够在select语句里面经过使用分区值来动态指明分区:

hive> set hive.exec.dynamic.partition.mode=nonstrict;

hive> insert into table test

    > partition (age)

    > select id, name,

    > tel, age

    > from wyp;

#################################################################

           这里输出了一堆Mapreduce任务信息,这里省略

#################################################################

Total MapReduce CPU Time Spent: 1 seconds 510 msec

OK

Time taken: 17.712 seconds

hive> select * from test;

OK

5       wyp1    131212121212    23

6       wyp2    134535353535    24

7       wyp3    132453535353    25

1       wyp     13188888888888  25

8       wyp4    154243434355    26

2       test    13888888888888  30

3       zs      899314121       34

Time taken: 0.399 seconds, Fetched: 7 row(s)

这种方法叫作动态分区插入,可是Hive中默认是关闭的,因此在使用前须要先把hive.exec.dynamic.partition.mode设置为nonstrict。固然,Hive也支持insert overwrite方式来插入数据,从字面能够看出,overwrite是覆盖的意思,执行完这条语句的时候,相应数据目录下的数据将会被覆盖,而insert into则不会。例子以下:

hive> insert overwrite table test

    > PARTITION (age)

    > select id, name, tel, age

    > from wyp;

Hive还支持多表插入,在Hive中,能够把insert语句倒过来,把from放在最前面,它的执行效果和放在后面是同样的,以下:

hive> show create table test3;

OK

CREATE  TABLE test3(

  id int,

  name string)

Time taken: 0.277 seconds, Fetched: 18 row(s)

hive> from wyp

    > insert into table test

    > partition(age)

    > select id, name, tel, age

    > insert into table test3

    > select id, name

    > where age>25;

 

hive> select * from test3;

OK

8       wyp4

2       test

3       zs

Time taken: 4.308 seconds, Fetched: 3 row(s)

能够在同一个查询中使用多个insert子句,这样只须要扫描一遍源表就能够生成多个不相交的输出。

6.1.4            建立表时导入

在实际状况中,表的输出结果可能太多,不适于显示在控制台上,这时候,将Hive的查询输出结果直接存在一个新的表中是很是方便的,称这种状况为CTAScreate table as select)以下:

hive> create table test4

    > as

    > select id, name, tel

    > from wyp;

hive> select * from test4;

OK

5       wyp1    131212121212

6       wyp2    134535353535

7       wyp3    132453535353

8       wyp4    154243434355

1       wyp     13188888888888

2       test    13888888888888

3       zs      899314121

Time taken: 0.089 seconds, Fetched: 7 row(s)

数据就插入到test4表中去了,CTAS操做是原子的,所以若是select查询因为某种缘由而失败,新表是不会建立的。

6.2  Hive数据导出的方式

Hive根据导出的地方不一样能够将导出方式分为三种:(1)导出到本地文件系统;(2)导出到HDFS中;(3)导出到Hive的另外一个表中,下面逐一介绍。

6.2.1            导出到本地文件系统

hive> insert overwrite local directory '/home/wyp/wyp'

    > select * from wyp;

这条HQL的执行须要启用Mapreduce完成,运行完这条语句以后,将会在本地文件系统的/home/wyp/wyp目录下生成文件,这个文件是Reduce产生的结果(这里生成的文件名是000000_0),咱们能够看看这个文件的内容:

[wyp@master ~/wyp]$ vim 000000_0

5^Awyp1^A23^A131212121212

6^Awyp2^A24^A134535353535

7^Awyp3^A25^A132453535353

8^Awyp4^A26^A154243434355

1^Awyp^A25^A13188888888888

2^Atest^A30^A13888888888888

3^Azs^A34^A899314121

能够看出,这是wyp表中的全部数据。数据中的列与列之间的分隔符是^A(ascii码是\00001)

Hive 0.11.0版本以前,数据的导出是不能指定列之间的分隔符的,只能用默认的列分隔符,也就是上面的^A来分割,这样导出来的数据很不直观,看起来很不方便。

若是用的Hive版本是0.11.0和以后版本,能够在导出数据的时候来指定列之间的分隔符,操做以下:

hive> insert overwrite local directory '/home/yangping.wu/local'

    > row format delimited

    > fields terminated by '\t'

    > select * from wyp;

 

 [wyp@master ~/local]$ vim 000000_0

5       wyp1    23      131212121212

6       wyp2    24      134535353535

7       wyp3    25      132453535353

8       wyp4    26      154243434355

1       wyp     25      13188888888888

2       test    30      13888888888888

3       zs      34      899314121

其实,还能够用hive-e-f参数来导出数据。其中-e表示后面直接接带双引号的sql语句;而-f是接一个文件,文件的内容为一个sql语句,以下:

[wyp@master ~/local]$  hive -e "select * from wyp" >> local/wyp.txt

[wyp@master ~/local]$cat wyp.txt

5       wyp1    23      131212121212

6       wyp2    24      134535353535

7       wyp3    25      132453535353

8       wyp4    26      154243434355

1       wyp     25      13188888888888

2       test    30      13888888888888

3       zs      34      899314121

获得的结果也是用\t分割的。也能够用-f参数实现:

[wyp@master ~/local]$ cat wyp.sql

select * from wyp

[wyp@master ~/local]$ hive -f wyp.sql >> local/wyp2.txt

上述语句获得的结果也是\t分割的。

6.2.2            导出到HDFS

和导入数据到本地文件系统同样的简单,能够用下面的语句实现:

hive> insert overwrite directory '/home/wyp/hdfs'

    > select * from wyp;

将会在HDFS/home/wyp/hdfs目录下保存导出来的数据。注意,和导出文件到本地文件系统的HQL少一个local,数据的存放路径就不同了。

6.2.3            导出到Hive的另外一个表中

hive> insert into table test

    > partition (age='25')

    > select id, name, tel

    > from wyp;

#################################################################

           这里输出了一堆Mapreduce任务信息,这里省略

#################################################################

Total MapReduce CPU Time Spent: 1 seconds 310 msec

OK

Time taken: 19.125 seconds

hive> select * from test;

OK

5       wyp1    131212121212    25

6       wyp2    134535353535    25

7       wyp3    132453535353    25

8       wyp4    154243434355    25

1       wyp     13188888888888  25

2       test    13888888888888  25

3       zs      899314121       25

Time taken: 0.126 seconds, Fetched: 7 row(s)

其实就是讲hive中一个表的内容导入到另外一个表中。

7         Hive索引

索引是标准的数据库技术,hive 0.7版本以后支持索引。Hive提供有限的索引功能,这不像传统的关系型数据库那样有(key)”的概念,用户能够在某些列上建立索引来加速某些操做,给一个表建立的索引数据被保存在另外的表中。 Hive的索引功能如今还相对较晚,提供的选项还较少。可是,索引被设计为可以使用内置的可插拔的java代码来定制,用户能够扩展这个功能来知足本身的需求。用户可使用EXPLAIN语法来分析HiveQL语句是否可使用索引来提高用户查询的性能。像RDBMS中的索引同样,须要评估索引建立的是否合理,毕竟,索引须要更多的磁盘空间,而且建立维护索引也会有必定的代价。 用户必需要权衡从索引获得的好处和代价。

下面介绍建立索引的方法:

1. 先建立表:

hive> create table a3( id int, name string)

> ROW FORMAT DELIMITED

> FIELDS TERMINATED BY '\t'

> STORED AS TEXTFILE;

2. 导入数据:

hive> load data local inpath 'apache-hive-0.13.1-bin/a21.txt'

    > overwrite into table a3;                              

Copying data from file:/usr/local/apache-hive-0.13.1-bin/a21.txt

Copying file: file:/usr/local/apache-hive-0.13.1-bin/a21.txt

Loading data to table default.a3

rmr: DEPRECATED: Please use 'rm -r' instead.

Deleted hdfs://localhost:9000/user/hive/warehouse/a3

Table default.a3 stats: [numFiles=1, numRows=0, totalSize=169, rawDataSize=0]

OK

Time taken: 0.468 seconds

3. 建立索引以前测试

hive> select * from a3 where id=28;

Total jobs = 1

Launching Job 1 out of 1

Number of reduce tasks is set to 0 since there's no reduce operator

Starting Job = job_1414112118511_0001, Tracking URL = http://h77.hadoop.org:8088/proxy/application_1414112118511_0001/

Kill Command = /usr/local/hadoop-2.4.1/bin/hadoop job  -kill job_1414112118511_0001

Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 0

2014-10-24 09:12:11,220 Stage-1 map = 0%,  reduce = 0%

2014-10-24 09:12:16,404 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.13 sec

MapReduce Total cumulative CPU time: 1 seconds 130 msec

Ended Job = job_1414112118511_0001

MapReduce Jobs Launched:

Job 0: Map: 1   Cumulative CPU: 1.13 sec   HDFS Read: 375 HDFS Write: 8 SUCCESS

Total MapReduce CPU Time Spent: 1 seconds 130 msec

OK

28      fdah

Time taken: 14.007 seconds, Fetched: 1 row(s)

一共用了14.007s

4. user建立索引

hive> create index a3_index on table a3(id)

    > as 'org.apache.hadoop.hive.ql.index.compact.CompactIndexHandler'

    > with deferred rebuild

    > in table a3_index_table;

OK

Time taken: 0.292 seconds

hive> alter index a3_index on a3 rebuild

    > ;

Total jobs = 1

Launching Job 1 out of 1

Number of reduce tasks not specified. Estimated from input data size: 1

In order to change the average load for a reducer (in bytes):

  set hive.exec.reducers.bytes.per.reducer=<number>

In order to limit the maximum number of reducers:

  set hive.exec.reducers.max=<number>

In order to set a constant number of reducers:

  set mapreduce.job.reduces=<number>

Starting Job = job_1414112118511_0002, Tracking URL = http://h77.hadoop.org:8088/proxy/application_1414112118511_0002/

Kill Command = /usr/local/hadoop-2.4.1/bin/hadoop job  -kill job_1414112118511_0002

Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1

2014-10-24 09:13:52,094 Stage-1 map = 0%,  reduce = 0%

2014-10-24 09:13:57,265 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 0.75 sec

2014-10-24 09:14:03,479 Stage-1 map = 100%,  reduce = 100%, Cumulative CPU 1.81 sec

MapReduce Total cumulative CPU time: 1 seconds 810 msec

Ended Job = job_1414112118511_0002

Loading data to table default.a3_index_table

rmr: DEPRECATED: Please use 'rm -r' instead.

Deleted hdfs://localhost:9000/user/hive/warehouse/a3_index_table

Table default.a3_index_table stats: [numFiles=1, numRows=20, totalSize=1197, rawDataSize=1177]

MapReduce Jobs Launched:

Job 0: Map: 1  Reduce: 1   Cumulative CPU: 1.81 sec   HDFS Read: 375 HDFS Write: 1277 SUCCESS

Total MapReduce CPU Time Spent: 1 seconds 810 msec

OK

Time taken: 17.976 seconds

hive> select * from a3_index_table;

OK

1       hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [0]

2       hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [6]

3       hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [12]

6       hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [40]

8       hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [18]

12      hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [46]

18      hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [54]

21      hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [22]

28      hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [128]

78      hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [119]

83      hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [136]

98      hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [153]

123     hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [27]

129     hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [161]

234     hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [80,109]

812     hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [144]

891     hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [34]

1231    hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [70,88]

2134    hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [61]

7897    hdfs://localhost:9000/user/hive/warehouse/a3/a21.txt    [98]

Time taken: 0.041 seconds, Fetched: 20 row(s)

这样对user表建立了一个索引。

5、对建立索引后的user再进行测试

hive> select * from a3 where id=28;                                  

Total jobs = 1

Launching Job 1 out of 1

Number of reduce tasks is set to 0 since there's no reduce operator

Starting Job = job_1414112118511_0003, Tracking URL = http://h77.hadoop.org:8088/proxy/application_1414112118511_0003/

Kill Command = /usr/local/hadoop-2.4.1/bin/hadoop job  -kill job_1414112118511_0003

Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 0

2014-10-24 09:15:40,439 Stage-1 map = 0%,  reduce = 0%

2014-10-24 09:15:46,617 Stage-1 map = 100%,  reduce = 0%, Cumulative CPU 1.21 sec

MapReduce Total cumulative CPU time: 1 seconds 210 msec

Ended Job = job_1414112118511_0003

MapReduce Jobs Launched:

Job 0: Map: 1   Cumulative CPU: 1.21 sec   HDFS Read: 375 HDFS Write: 8 SUCCESS

Total MapReduce CPU Time Spent: 1 seconds 210 msec

OK

28      fdah

Time taken: 11.924 seconds, Fetched: 1 row(s)

时间用了11.924s比没有建立索引的效果好些,数据量大的时候效果会更明显。

8         JDBC链接Hive Server

能够经过CLIClientWeb UIHive提供的用户接口来和Hive通讯,但这三种方式最经常使用的是CLIClientHive的客户端,用来链接至Hive Server。在启动Client模式的时候,须要指出Hive Server所在节点,而且在该节点启动Hive ServerWUI是经过浏览器访问 Hive。下面介绍经过HiveServer来操做Hive

Hive提供了JDBC驱动,使得咱们能够用Java代码来链接Hive并进行一些类关系型数据库的SQL语句查询等操做。同关系型数据库同样,也须要将Hive的服务打开;在Hive 0.11.0版本以前,只有HiveServer服务可用,得在程序操做Hive以前,在安装Hive的服务器上打开HiveServer服务,以下所示:

#bin/hive --service hiveserver -p 10002

Starting Hive Thrift Server

上面表明你已经成功的在端口为10002(默认的端口是10000)启动了hiveserver服务。这时候,你就能够经过Java代码来链接hiveserver,代码以下:

import java.sql.SQLException;

import java.sql.Connection;

import java.sql.ResultSet;

import java.sql.Statement;

import java.sql.DriverManager;

 

public class Testmzl {

 

       private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";

 

       public static void main(String[] args) throws SQLException {

              try {

                     Class.forName(driverName);

              } catch (ClassNotFoundException e) {

                     e.printStackTrace();

                     System.exit(1);

              }

 

              Connection con = DriverManager.getConnection(

                            "jdbc:hive://192.168.1.77:10002/default", "", "");

              Statement stmt = con.createStatement();

              String tableName = "wyp";

              stmt.execute("drop table if exists " + tableName);

              stmt.execute("create table " + tableName + " (key int, value string)");

              System.out.println("Create table success!");

              // show tables

              String sql = "show tables";

              System.out.println("Running: " + sql);

              ResultSet res = stmt.executeQuery(sql);

              while (res.next()) {

                     System.out.println(res.getString(1));

              }

 

              // describe table

              sql = "describe " + tableName;

              System.out.println("Running: " + sql);

              res = stmt.executeQuery(sql);

              while (res.next()) {

                     System.out.println(res.getString(1) + "\t" + res.getString(2));

              }

 

              sql = "select * from " + tableName;

              res = stmt.executeQuery(sql);

              while (res.next()) {

                     System.out.println(String.valueOf(res.getInt(1)) + "\t"

                                   + res.getString(2));

              }

 

              sql = "select count(1) from " + tableName;

              System.out.println("Running: " + sql);

              res = stmt.executeQuery(sql);

              while (res.next()) {

                     System.out.println(res.getString(1));

              }

       }

}

编译上面的代码,以后就能够运行,结果以下:

Create table success!

Running: show tables 'wyphao'

wyphao

Running: describe wyphao

key                     int               

value                   string            

Running: select count(1) from wyphao

0

上面用Java链接HiveServer,而HiveServer自己存在不少问题(好比:安全性、并发性等);针对这些问题,Hive0.11.0版本提供了一个全新的服务:HiveServer2,这个很好的解决HiveServer存在的安全性、并发性等问题。这个服务启动程序在${HIVE_HOME}/bin/hiveserver2里面,能够经过下面的方式来启动HiveServer2服务:

$HIVE_HOME/bin/hiveserver2

也能够经过下面的方式启动HiveServer2

$HIVE_HOME/bin/hive --service hiveserver2

两种方式效果同样。可是以前的java程序须要修改两个地方,以下所示:

private static String driverName = "org.apache.hadoop.hive.jdbc.HiveDriver";

改成

private static String driverName = "org.apache.hive.jdbc.HiveDriver";

 

Connection con = DriverManager.getConnection("jdbc:hive://localhost:10002/default", "", "");

改成

Connection con = DriverManager.getConnection("jdbc:hive2://localhost:10000/default", "", "");

其余的不变就能够了。

 

9         常见问题

9.1  disabled stack guard

在安装运行hadoop时会出现下面的错误:

Hadoop 2.2.0 - warning: You have loaded library /home/hadoop/2.2.0/lib/native/libhadoop.so.1.0.0 which might have disabled stack guard.

具体出错内容以下:

Unable to load native-hadoop library for your platform... using builtin-java classes where applicable

Starting namenodes on [Java HotSpot(TM) 64-Bit Server VM warning: You have loaded library /home/hadoop/2.2.0/lib/native/libhadoop.so.1.0.0 which might have disabled stack guard. The VM will try to fix the stack guard now.

It's highly recommended that you fix the library with 'execstack -c <libfile>', or link it with '-z noexecstack'.

localhost]

sed: -e expression #1, char 6: unknown option to `s'

HotSpot(TM): ssh: Could not resolve hostname HotSpot(TM): Name or service not known

64-Bit: ssh: Could not resolve hostname 64-Bit: Name or service not known

Java: ssh: Could not resolve hostname Java: Name or service not known

Server: ssh: Could not resolve hostname Server: Name or service not known

VM: ssh: Could not resolve hostname VM: Name or service not known

解决方法:

[root@h77 hadoop-2.4.1]#vim etc/hadoop/hadoop-env.sh

HADOOP_PREFIX变量的定义后面,HADOOP_OPTS变量的定义前面添加下列变量:

export HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_PREFIX}/lib/native

export HADOOP_OPTS="-Djava.library.path=$HADOOP_PREFIX/lib"

9.2  javax.jdo.option.ConnectionURL配置的问题

Hive安装过程当中出现 The reference to entity "createDatabaseIfNotExist" must end with the ';' delimiter.问题,具体以下所示:

[Fatal Error] hive-site.xml:132:95: The reference to entity "createDatabaseIfNotExist" must end with the ';' delimiter.

14/10/23 11:15:04 FATAL conf.Configuration: error parsing conf file:/usr/local/apache-hive-0.13.1-bin/conf/hive-site.xml

org.xml.sax.SAXParseException; systemId: file:/usr/local/apache-hive-0.13.1-bin/conf/hive-site.xml; lineNumber: 132; columnNumber: 95; The reference to entity "createDatabaseIfNotExist" must end with the ';' delimiter.

显示以下所示:

由于hive-site.xml中的javax.jdo.option.ConnectionURL配置项引发的,以下所示:

<property>

<name>javax.jdo.option.ConnectionURL</name>

<value>jdbc:mysql://localhost:3306/hive_hdp?characterEncoding=UTF-8&createDatabaseIfNotExist=true</value>

<description>JDBC connect string for a JDBC metastore</description>

</property>

正确配置以下:

<property>

<name>javax.jdo.option.ConnectionURL</name>

<value>jdbc:mysql://localhost:3306/hive_hdp?characterEncoding=UTF-8&amp;createDatabaseIfNotExist=true</value>

<description>JDBC connect string for a JDBC metastore</description>

</property>

这是由于xml文件中的编码规则引发的。

xml文件中有如下几类字符要进行转义替换以下表所示:

符号

Xml表示

含义

&lt;

小于号

&gt;

大于号

&amp;

&

&apos;

'

单引号

&quot;

"

双引号

因此javax.jdo.option.ConnectionURL项中的&符号须要用&amp;表示。

10         Hive优化

10.1  简单查询不启用Mapreduce job

若是你想查询某个表的某一列,Hive默认是会启用MapReduce Job来完成这个任务:

hive> SELECT id, money FROM m limit 10;

Total MapReduce jobs = 1

Launching Job 1 out of 1

Number of reduce tasks is set to 0 since there's no reduce operator

Cannot run job locally: Input Size (= 235105473) is larger than

hive.exec.mode.local.auto.inputbytes.max (= 134217728)

Starting Job = job_1384246387966_0229, Tracking URL =

 

http://l-datalogm1.data.cn1:9981/proxy/application_1384246387966_0229/

 

Kill Command = /home/q/hadoop-2.2.0/bin/hadoop job

-kill job_1384246387966_0229

hadoop job information for Stage-1: number of mappers: 1;

number of reducers: 0

2013-11-13 11:35:16,167 Stage-1 map = 0%,  reduce = 0%

2013-11-13 11:35:21,327 Stage-1 map = 100%,  reduce = 0%,

Cumulative CPU 1.26 sec

2013-11-13 11:35:22,377 Stage-1 map = 100%,  reduce = 0%,

Cumulative CPU 1.26 sec

MapReduce Total cumulative CPU time: 1 seconds 260 msec

Ended Job = job_1384246387966_0229

MapReduce Jobs Launched:

Job 0: Map: 1   Cumulative CPU: 1.26 sec 

HDFS Read: 8388865 HDFS Write: 60 SUCCESS

Total MapReduce CPU Time Spent: 1 seconds 260 msec

OK

1       122

1       185

1       231

1       292

1       316

1       329

1       355

1       356

1       362

1       364

Time taken: 16.802 seconds, Fetched: 10 row(s)

启用MapReduce Job会消耗系统开销,对于这个问题,从Hive0.10.0版本开始,对于简单的不须要聚合的相似SELECT <col> from <table> LIMIT n语句,不须要起MapReduce job,直接经过Fetch task获取数据,能够经过下面几种方法实现:

方法一:

hive> set hive.fetch.task.conversion=more;

hive> SELECT id, money FROM m limit 10;

OK

1       122

1       185

1       231

1       292

1       316

1       329

1       355

1       356

1       362

1       364

Time taken: 0.138 seconds, Fetched: 10 row(s)

上面set hive.fetch.task.conversion=more;开启了Fetch任务,因此对于上述简单的列查询再也不启用MapReduce job

方法二:

bin/hive --hiveconf hive.fetch.task.conversion=more

方法三:

上面的两种方法均可以开启了Fetch任务,可是都是临时起做用的;若是你想一直启用这个功能,能够在${HIVE_HOME}/conf/hive-site.xml里面加入如下配置:

<property>

<name>hive.fetch.task.conversion</name>

<value>more</value>

<description>Some select queries can be converted to single FETCH task

minimizing latency.Currently the query should be single

sourced not having any subquery and should not have

any aggregations or distincts (which incurrs RS),

lateral views and joins.

1. minimal : SELECT STAR, FILTER on partition columns, LIMIT only

2. more    : SELECT, FILTER, LIMIT only (+TABLESAMPLE, virtual columns)

</description>

</property>

这样就能够长期启用Fetch任务了。

11         参考博文

本文主要参考下面的博文:

http://www.iteblog.com/archives/category/hive

相关文章
相关标签/搜索