Hive

一、hive简介

       1. Hive 是建立在 Hadoop  上的数据仓库基础构架。它提供了一系列的工具,可以用来进行数据提取转化加载(ETL ),这是一种可以存储、查询和分析存储在 Hadoop  中的大规模数据的机制。Hive 定义了简单的类 SQL  查询语言,称为 HQL ,它允许熟悉 SQL  的用户查询数据。

     2. Hive是SQL解析引擎,它将SQL语句转译成M/R Job然后在Hadoop执行(大部分的查询由 MapReduce 完成(包含 * 的查询,比如 select * from table 不会生成 MapRedcue 任务))。

     3.Hive的表其实就是HDFS的目录/文件,按表名把文件夹分开。如果是分区表,则分区值是子文件夹名

二、hive架构

   Hive_第1张图片

三、hive的metastore

   1、metastore是hive元数据的集中存放地。metastore默认使用内嵌的derby数据库作为存储引擎
   2、Derby引擎的缺点:一次只能打开一个会话(用户切换到不同目录下启动hive都会创建自己的MetaStore),不能多用户共享
   3、使用Mysql作为外置存储引擎,多用户同时访问 


四、hive与传统数据库

     

注意:由于 Hive 是针对数据仓库应用设计的,而数据仓库的内容是读多写少的。因此,Hive 中不支持对数据的改写和添加,所有的数据都是在加载的时候中确定好的


五、hive的数据存储

      Hive的数据存储基于Hadoop HDFS,没有专门的数据存储格式,存储结构主要包括:数据库、文件、表、视图,Hive默认可以直接加载文本文件(TextFile),还支持sequence file 、RC file,创建表时,指定Hive数据的列分隔符与行分隔符,Hive即可解析数据。

1、数据库

      默认数据库"default",使用#hive命令后,不使用hive>use <数据库名>,系统默认的数据库。
      可以创建一个新库hive > create database test_dw;

2、表

      <1>Table 内部表

          每一个 Table 在 Hive 中都有一个相应的目录存储数据。例如,一个表 test,它在 HDFS 中的路是user/hive/warehouse/test。 warehouse是在 hive-site.xml 中由 ${hive.metastore.warehouse.dir} 指定的数据仓库的目录,所有的 Table 数据(不包括 External Table)都保存在这个目录中。删除表时,元数据与数据都会被删除

例子:

        创建表
                    hive>create table inner_table (key string);
        加载数据
                    hive>load data local inpath '/root/inner_table.dat' into table inner_table;

     <2>分区表

           在hive中查询时一般会扫描整个表内容,会消耗很多时间做没必要的工作,因此出现了分区表!!

           Partition 对应于数据库的 Partition 列的密集索引,在 Hive 中,表中的一个 Partition 对应于表下的一个目录,所有的 Partition 的数据都存储在对应的目录中
            例如:test表中包含 date 和 city 两个 Partition,则对应于date=20130201, city = bj 的 HDFS 子目录/warehouse/test/date=20130201/city=bj

例子:

    创建表
         create table partition_table(rectime string,msisdn string) partitioned by(daytime string,city string) row format delimited fields terminated by '\t' stored as TEXTFILE;
    加载数据到分区
         load data local inpath '/home/partition_table.dat' into table partition_table partition (daytime='2013-02-01',city='bj');

    增加、删除分区

        alter table partition_table add(drop) partition (daytime='2013-02-04',city='bj')


    <3>桶表

           桶表是对数据进行哈希取值然后与桶的数量取模。把数据放到对应的文件中。
      创建表
      create table bucket_table(id string) clustered by(id) into 3 buckets;(3个桶就是对应个文件)
      加载数据
      set hive.enforce.bucketing = true;
      insert into table bucket_table select name from stu;
            
     

     <4>外部表

           (1)指向已经在 HDFS 中存在的数据,可以创建 Partition
           (2)内部表 的创建过程和数据加载过程(这两个过程可以在同一个语句中完成),在加载数据的过程中,实际数据会被移动到数据仓库目录中;之后对数据对访问将会直接在数据仓库目录中完成。删除表时,表中的数据和元数据将会被同时删除;
               外部表 只有一个过程,加载数据和创建表同时完成,并不会移动到数据仓库目录中,只是与外部数据建立一个链接。当删除一个 外部表 时,仅删除该链接

         创建表
                hive>create external table external_table1 (key string) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\t' location '/home/external';


六、创建表

      1、create语法来创建

create external table employee(
   name string,
   salary float,
   subordinates array<string>,
   deductions map<string,float>,
   address struct<street:string,city:string,state:string,zip:int>
)
row format delimited fields terminated by '\t'
collection items terminated by ','
map keys terminated by ':',
lines terminated by '\n'
stored as textfile
location '/data';


data数据的格式是这样的:


     2、由一个表创建另一个表

            create table test1 like test2;

     3、由其他表查询创建表

           create table test as select name from test1;

七、加载数据

    1、内表加载数据

             (1)创建表时加载

                    create table newtable as select col1,col2 from oldtable;

             (2)本地数据加载

                    load data local inpath 'localpath' [overwrite] into table tablename;

             (3)hdfs数据加载

                    load data inpath 'hdfspath' [overwrite] into table tablename;

                     注意:此操作是移动数据,hdfs上的数据将会移动到数据仓库

             (4)由查询语句加载数据

                     insert  [overwrite | into]  table tablename

                     select col1,col2 from table where...........

        2、外表数据加载

              (1)创建表时指定数据位置

                   create external table tablename() .........location 'path';

              (2)查询插入,同内表

                    注意:这个时候外表在数据仓库中是存在的,只不过这种方式对于外表来说没有什么意义!

       3、hive分区表数据加载

               (1)本地数据加载

                    load data local inpth 'localpath' [overwrite] into table tablename partition(pn=‘’);

               (2)加载hdfs数据

                    load data inpath 'hdfspath' [overwrite] into table tablename partition(pn='')

               (3)由查询语句加载数据

                   insert [overwrite]  into table tablename partion(pn='')

             select col1,col2 from table where.....   

 八、数据的导出方式

       1、hadoop命令的方式

                   hadoop fs -get[text]  /user/hive/warehouse/tablename/* /hive_data(本地路径)

           2、通过insert的方式

                   insert overwrite [local] directory '/data' row format delimited fields terminated by '\t'

                   select col from tablename;

 九、动态分区        

          *不需要为不同的分区添加不同的插入语句

          *分区不确定,需要从数据中获取

        1、必须设置的参数

            set hive.exec.dynamic.partition=true;//使用动态分区

            set hive.exec.dynamic.partition.mode=nostrick;//无限制模式,如果是strict,则比不有一个静态分区,且放在最前面

        2、创建动态分区表及其插入数据            

   

十、表属性操作

       1、修改表名

                 alter table tablename rename to new_tablename;

        2、修改列名 

                 alter table tablename change column c1 c2 string;

        3、 增加列

                  alter table tablename add columns (c1 string,c2 long);

        4、修改分隔符

                  alter table tablename [partition(dt='xxxxx')] set serdeproperties ('field.delim'='\t');

        5、修改location

                  alter table tablename  [partition()] set location 'path';


十一、hive高级查询

       1、order by

             例子:select col1,col2 from tablename where...

                        order by col1,col2 [asc | desc];

             注意:

                     * 可以有多列排序,默认按照字典排序

                     * order by为全局排序

     * order by需要reduce操作,且只有一个reduce

              mapreduce原理:

                Hive_第2张图片

         2、group by

             *按照某些字段的值进行分组,有相同值放在一起(可以拿来去重操作)

             样例:

                 select col1,[col2] from tablename 

                 where....

                 group by col1,[col2]

             注意:select 后面非聚合列必须出现在group by中

             特征:

                  使用了reduce操作,受限于reduce数量,可以设置参数set mapred.reduce.tasks=n;

             mapreduce原理:

                        

           3、Join

              *join等值连接、left outer join左外连接、right outer join右外连接

              例子:

                     Hive_第3张图片

                  select a.col,a.col2,b.col4 from a join b on a.col=b.col3

                 输出:

                    

                mapreduce原理:

                    Hive_第4张图片

            4、mapjoin(join的优化操作,不走reduce)

                   *在map端把小标加载到内存,然后读取大表,和内存中的小表完成连接操作

                   优缺点:

                          优点:不消耗reduce资源

                           缺点:占用部分内存,因为每个map都会加载一次小表;生成较多小文件

                  配置参数:

                        select /*+mapjoin(n)*/ m.col,m.col2,n.col3 from m join n on m.col=n.col 

                   mapreduce原理:

                           Hive_第5张图片

                 mapjoin的使用场景:

                        *有一张很小的表

                        *不等值连接操作

         5、distribute by 和sort by

               *distribute by分散数据

                       distribute by col,按照col列把数据分散到不同的reduce

               *sort by排序

                       sort by col,对每个reduce局部对col排序

                     *样例    

                       set mapred.reduce.tasks=3;//设置reduce数量为3

                       select col1,col2 from m

                       distribute by col1

                       sort by col1 asc,col2 asc;       

                          *对比

                       Hive_第6张图片

                 mapreduce原理:

                   Hive_第7张图片    

          6、union all

                     *多个表的数据合并成一个表

                                  样例:

                             select col

                             from(select a as col from t1

                                      union all

                                      select b as col from t2

                            )tmp;


十二、hive函数

      

   1、内置函数

                   http://blog.csdn.net/wisgood/article/details/17376393

     2、hive自定义函数

               <1>UDF

                      Hive_第8张图片

        例子:

              写一个自定义函数,要求能对某一列的数据对某一个数比大小,返回True,false

package com.hive.hadoop;

import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;

public class udfTest extends UDF{
	public boolean evaluate(Text t1,Text t2)
	{
		if(t1==null||t2==null)
			return false;
		double d1=Double.parseDouble(t1.toString());
		double d2=Double.parseDouble(t2.toString());
		if(d1>d2)
			return true;
		else 
			return false;
	}
}

             Hive执行add jar: 

                     add jar /function.jar

        Hive执行创建模板函数

                    create temporary function bigthan as ‘com.hive.hadoop.udfTest’ 

        Hql中执行

                    Select col1,col2 ,bigthan(col2,5) from tablename;

                                            

          <2>UDAF

                Hive_第9张图片

例子:在上例的基础之上,统计一下大于基数的个数

package com.hive.hadoop;

import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.parse.SemanticException;
import org.apache.hadoop.hive.ql.udf.generic.AbstractGenericUDAFResolver;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDAFEvaluator;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
import org.apache.hadoop.hive.serde2.typeinfo.TypeInfo;
import org.apache.hadoop.io.LongWritable;

public class CountBigThan extends AbstractGenericUDAFResolver{
	//对参数进行判断
	@Override
	public GenericUDAFEvaluator getEvaluator(TypeInfo[] paramaters)
			throws SemanticException {
		if(paramaters.length!=2)
		{
			throw new UDFArgumentTypeException(paramaters.length-1,
					"Exactly two argument is expected.");
		}
		return new GenericUDAFCountBigThanEvaluator();
	}
	
	//这个类来处理逻辑
    public static class  GenericUDAFCountBigThanEvaluator extends GenericUDAFEvaluator{

        private LongWritable result;
        private PrimitiveObjectInspector inputOI1;
        private PrimitiveObjectInspector inputOI2;
     
        //参数检查函数,每个阶段相关方法执行之前都会执行此函数
        //map阶段:parameters长度与udaf输入的参数个数有关
        //reduce阶段:parameters长度为1
    	@Override
		public ObjectInspector init(Mode m, ObjectInspector[] parameters)
				throws HiveException {
			super.init(m, parameters);
			
			//最终结果变量
			result=new LongWritable(0);
			
			//把原始参数转化一下,方便后面的通用类型转化
			inputOI1=(PrimitiveObjectInspector)parameters[0];
			if(parameters.length>1)
			{
				inputOI2=(PrimitiveObjectInspector)parameters[1];
			}
			return PrimitiveObjectInspectorFactory.writableLongObjectInspector;
		}
    	
    	//此方法在map执行,用来缓存临时的值
		@Override
		public AggregationBuffer getNewAggregationBuffer() throws HiveException {
			CountAgg agg=new CountAgg();//缓存一个long类型的变量(值是1),用来计数;需要重新定义一个类
			//重置,需要再次使用的时候要重置为0
			reset(agg);
			return agg;
		}
       
		@Override
		public void iterate(AggregationBuffer agg, Object[] par)
				throws HiveException {
			assert(par.length==2);
			if(par==null||par[0]==null||par[1]==null)
				return;
			double base=PrimitiveObjectInspectorUtils.getDouble(par[0], inputOI1);
			double tmp=PrimitiveObjectInspectorUtils.getDouble(par[1], inputOI2);
			if(base>tmp)
				((CountAgg)agg).count++;
		}
		
		@Override
		public Object terminatePartial(AggregationBuffer agg)
				throws HiveException {
			result.set(((CountAgg)agg).count);
			return result;
		}
	
		@Override
		public void merge(AggregationBuffer agg, Object partial)//合并,这个partial是上面函数返回的对象
				throws HiveException {
			if(partial!=null)
			{
				long p=PrimitiveObjectInspectorUtils.getLong(partial, inputOI1);
				((CountAgg)agg).count+=p;
			}
		}
		
		@Override
		public Object terminate(AggregationBuffer agg) throws HiveException {
			result.set(((CountAgg)agg).count);
			return result;
		}  	
		
		//重置方法
		@Override
		public void reset(AggregationBuffer CountAgg) throws HiveException {
			CountAgg agg=(CountAgg)CountAgg;
			agg.count=0;
		}

		//新建类
    	public static class CountAgg implements AggregationBuffer{
    		long count;
    	}
    }
}


Mode枚举类:

 

Hive_第10张图片

Hive_第11张图片


查看源码:

      src\ql\src\java\org\apache\hadoop\hive\ql\udf\generic

你可能感兴趣的:(hadoop,hive)