ToB企服应用市场:ToB评测及商务社交产业平台

标题: Hive基础知识大全 [打印本页]

作者: 卖不甜枣    时间: 2024-8-12 22:18
标题: Hive基础知识大全
Hive基础知识大全


  
1、Hive根本概念

1.1、Hive简介

Hive本质是将SQL转化为MapReduce的任务进行计算,底层由HDFS来提供数据存储。说白了hive可以理解为一个将SQL转换为MapReduce的任务的工具,乃至更进一步说hive就是MapReduce的一个客户端。
1.2、什么是Hive(口试题)


1.3、为什么要使用Hive


1.4、Hive的特点


1.5、Hive的优缺点

   长处
  
   缺点
  
   迭代算法:迭代式算法是指那些需要反复实行同一组计算步骤的算法,每次迭代的结果依赖于前一次迭代的结果。
  1.6、hive和mysql的区别


1.7、hive的应用场景


   名词表明
  1. PV(Page View)访问量, 即页面浏览量或点击量,衡量网站用户访问的网页数量;在一定统计周期内用户每打开或刷新一个页面就记录1次,多次打开或刷新同一页面则浏览量累计。
  2. UV(Unique Visitor)独立访客,统计1天内访问某站点的用户数(以cookie为依据);访问网站的一台电脑客户端为一个访客。可以理解成访问某网站的电脑的数量。网站判断来访电脑的身份是通过来访电脑的cookies实现的。如果更换了IP后但不清除cookies,再访问相同网站,该网站的统计中UV数是不变的。如果用户不保存cookies访问、清除了cookies或者更换设备访问,计数会加1。00:00-24:00内相同的客户端多次访问只计为1个访客。
复制代码
1.8、Hive架构


1.8.1、Hive Client

   Hive Client 是与Hive交互的工具,用户可以通过它提交HiveQL查询、实行数据操纵并获取结果。
  
1.8.2、Hive Metastore(Hive的元数据存储)

   在Apache Hive中,Metastore(元数据存储)饰演着非常重要的脚色,它负责管理和存储Hive表的元数据信息。
  元数据存储在数据库中,默认存在自带的derby数据库(单用户局限性)中,保举使用Mysql进行存储。
  
1.8.3、sql语句是如何转换成MapReduce任务的(重点!!!!!!!!!!!!)


2、Hive的三种交互方式

(1) 第一种交互方式

   shell交互Hive,用命令hive启动一个hive的shell命令行,在命令行中输入sql或者命令来和Hive交互。
  1. 服务端启动metastore服务(后台启动):nohup hive --service metastore &
  2. 进入命令:hive
  3. 退出命令行:quit;
复制代码
(2) 第二种交互方式

   Hive启动为一个服务器,对外提供服务,其他机器可以通过客户端通过协议连接到服务器,来完成访问操纵,这是生产环境用法最多的
  1. 服务端启动hiveserver2服务:
  2. nohup hive --service metastore &
  3. nohup hiveserver2 &
  4. 需要稍等一下,启动服务需要时间:
  5. beeline -u jdbc:hive2://master:10000 -n root
  6. 退出命令行:!exit
复制代码
(3) 第三种交互方式

   使用 –e 参数来直接实行hql的语句
  1. bin/hive -e "show databases;
  2. "
复制代码
  使用 –f 参数通过指定文本文件来实行hql的语句
  特点:实行完sql后,回到linux命令行。
  1. vim hive.sql
  2. create database bigdata30_test;
  3. use bigdata30_test;
  4. create table test1
  5. (
  6.     id bigint,
  7.     name string
  8. )
  9. ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
  10. show tables;
复制代码
  1. hive -f hive.sql
复制代码
(4) hive cli和beeline cli的区别


3、Hive元数据

Hive元数据库中一些重要的表布局及用途**,方便Impala、SparkSQL、Hive等组件访问元数据库的理解。
1、存储Hive版本的元数据表(VERSION),该表比力简单,但很重要,假如这个表出现问题,根本进不来Hive-Cli。比如该表不存在,当启动Hive-Cli的时间,就会报错“Table ‘hive.version’ doesn’t exist”
2、Hive数据库相干的元数据表(DBS、DATABASE_PARAMS)
DBS:该表存储Hive中所有数据库的根本信息。
​ DATABASE_PARAMS:该表存储数据库的相干参数。
3、Hive表和视图相干的元数据表
​ 主要有TBLS、TABLE_PARAMS、TBL_PRIVS,这三张表通过TBL_ID关联。
TBLS:该表中存储Hive表,视图,索引表的根本信息。
​ TABLE_PARAMS:该表存储表/视图的属性信息。
​ TBL_PRIVS:该表存储表/视图的授权信息。
4、Hive文件存储信息相干的元数据表
​ 主要涉及SDS、SD_PARAMS、SERDES、SERDE_PARAMS,由于HDFS支持的文件格式很多,而建Hive表时间也可以指定各种文件格式,Hive在将HQL剖析成MapReduce时间,需要知道去哪里,使用哪种格式去读写HDFS文件,而这些信息就保存在这几张表中。
SDS:该表保存文件存储的根本信息,如INPUT_FORMAT、OUTPUT_FORMAT、是否压缩等。TBLS表中的SD_ID与该表关联,可以获取Hive表的存储信息。
​ SD_PARAMS: 该表存储Hive存储的属性信息。
​ SERDES:该表存储序列化使用的类信息。
SERDE_PARAMS:该表存储序列化的一些属性、格式信息,比如:行、列分隔符。
5、Hive表字段相干的元数据表
​ 主要涉及COLUMNS_V2:该表存储表对应的字段信息。
4、Hive的根本操纵

4.1 Hive库操纵

4.1.1 创建数据库

   1)创建一个数据库,数据库在HDFS上的默认存储路径是/user/hive/warehouse/*.db
  1. create database testdb;
复制代码
  2)避免要创建的数据库已经存在错误,增加if not exists判断。(尺度写法)
  1. create database [if not exists] testdb;
  2. create database if not exists bigdata30_test2;
复制代码
4.1.2 创建数据库和位置

  1. create database if not exists bigdata30_test3 location '/bigdata30/liliangdb';
复制代码
4.1.3 修改数据库

   数据库的其他元数据信息都是不可更改的,包括数据库名和数据库所在的目录位置。(重点关注哪些不能改,以及为什么!!
  1. alter database dept set dbproperties('createtime'='20220531');
复制代码
4.1.4 数据库详细信息

   1)表现数据库(show)
  1. show databases;
复制代码
  2)可以通过like进行过滤
  1. show databases like 't*';
复制代码
  3)检察详情(desc)
  1. desc database testdb;
复制代码
  4)切换数据库(use)
  1. use testdb;
复制代码
4.1.5 删除数据库(将删除的目录移动到回收站中)

   1)最简写法
  1. drop database testdb;
复制代码
  2)假如删除的数据库不存在,最好使用if exists判断数据库是否存在。否则会报错:FAILED: SemanticException [Error 10072]: Database does not exist: db_hive
  1. drop database if exists testdb;
复制代码
  3)假如数据库不为空,使用cascade命令进行逼迫删除。报错信息如下FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. InvalidOperationException(messageatabase db_hive is not empty. One or more tables exist.)
  1. drop database if exists testdb cascade;
复制代码
4.2、Hive数据类型

4.2.1、基础数据类型

类型Java数据类型描述TINYINTbyte8位有符号整型。取值范围:-128~127。SMALLINTshort16位有符号整型。取值范围:-32768~32767。INTint32位有符号整型。取值范围:-2 31 ~2 31 -1。BIGINTlong64位有符号整型。取值范围:-2 63 +1~2 63 -1。BINARY二进制数据类型,目前长度限定为8MB。FLOATfloat32位二进制浮点型。DOUBLEdouble64位二进制浮点型。DECIMAL(precision,scale)10进制精确数字类型。precision:表现最多可以表现多少位的数字。取值范围:1 <= precision <= 38。scale:表现小数部门的位数。取值范围: 0 <= scale <= 38。假如不指定以上两个参数,则默认为decimal(10,0)。VARCHAR(n)变长字符类型,n为长度。取值范围:1~65535。CHAR(n)固定长度字符类型,n为长度。最大取值255。长度不足则会填充空格,但空格不参与比力。STRINGstring字符串类型,目前长度限定为8MB。DATE日期类型,格式为yyyy-mm-dd。取值范围:0000-01-01~9999-12-31。DATETIME日期时间类型。取值范围:0000-01-01 00:00:00.000~9999-12-31 23.59:59.999,精确到毫秒。TIMESTAMP与时区无关的时间戳类型。取值范围:0000-01-01 00:00:00.000000000~9999-12-31 23.59:59.999999999,精确到纳秒。说明 对于部门时区相干的函数,例如cast( as string),要求TIMESTAMP按照与当前时区符合的方式来展现。BOOLEANbooleanBOOLEAN类型。取值:True、False。 4.2.2、复杂数据类型

类型定义方法构造方法ARRAYarray<int>``array<struct<a:int, b:string>>array(1, 2, 3)``array(array(1, 2), array(3, 4))MAPmap<string, string>``map<smallint, array<string>>map(“k1”, “v1”, “k2”, “v2”)``map(1S, array(‘a’, ‘b’), 2S, array(‘x’, ‘y’))STRUCTstruct<x:int, y:int>struct<field1:bigint, field2:array<int>, field3:map<int, int>> named_struct(‘x’, 1, ‘y’, 2)named_struct(‘field1’, 100L, ‘field2’, array(1, 2), ‘field3’, map(1, 100, 2, 200))   Hive有三种复杂数据类型ARRAY、MAP 和 STRUCT。ARRAY和MAP与Java中的Array和Map雷同,而STRUCT与C语言中的Struct雷同,它封装了一个定名字段集合,复杂数据类型允许任意条理的嵌套。还有一个uniontype< 所有类型,所有类型… > 。
  ​ 数组:array< 所有类型 >;
​ Map < 根本数据类型,所有数据类型 >;
​ struct < 名:所有类型[注释] >;
​ uniontype< 所有类型,所有类型… >
  4.3、Hive表操纵

   Hive的存储格式:
  Hive没有专门的数据文件格式,常见的有以下几种:
  ​ TEXTFILE
​ SEQUENCEFILE
​ AVRO
RCFILE
ORCFILE
PARQUET
  1. TextFile:
  2.        TEXTFILE 即正常的文本格式,是Hive默认文件存储格式,因为大多数情况下源数据文件都是以text文件格式保存(便于查看验数和防止乱码)。此种格式的表文件在HDFS上是明文,可用hadoop fs -cat命令查看,从HDFS上get下来后也可以直接读取。
  3.         TEXTFILE 存储文件默认每一行就是一条记录,可以指定任意的分隔符进行字段间的分割。但这个格式无压缩,需要的存储空间很大。虽然可结合Gzip、Bzip2、Snappy等使用,使用这种方式,Hive不会对数据进行切分,从而无法对数据进行并行操作。
  4. 一般只有与其他系统由数据交互的接口表采用TEXTFILE 格式,其他事实表和维度表都不建议使用。
  5. RCFile:
  6. Record Columnar的缩写。是Hadoop中第一个列文件格式。能够很好的压缩和快速的查询性能。通常写操作比较慢,比非列形式的文件格式需要更多的内存空间和计算量。 RCFile是一种行列存储相结合的存储方式。首先,其将数据按行分块,保证同一个record在一个块上,避免读一个记录需要读取多个block。其次,块数据`列式存储`,有利于数据压缩和快速的列存取。
  7. ORCFile:
  8. Hive从0.11版本开始提供了ORC的文件格式,ORC文件不仅仅是一种列式文件存储格式,最重要的是有着很高的压缩比,并且对于MapReduce来说是可切分(Split)的。因此,在Hive中使用ORC作为表的文件存储格式,不仅可以很大程度的节省HDFS存储资源,而且对数据的查询和处理性能有着非常大的提升,因为ORC较其他文件格式压缩比高,查询任务的输入数据量减少,使用的Task也就减少了。ORC能很大程度的节省存储和计算资源,但它在读写时候需要消耗额外的CPU资源来压缩和解压缩,当然这部分的CPU消耗是非常少的。
  9. Parquet:
  10. 通常我们使用关系数据库存储结构化数据,而关系数据库中使用数据模型都是扁平式的,遇到诸如数组、Map和自定义Struct的时候就需要用户在应用层解析。但是在大数据环境下,通常数据的来源是服务端的埋点数据,很可能需要把程序中的某些对象内容作为输出的一部分,而每一个对象都可能是嵌套的,所以如果能够原生的支持这种数据,这样在查询的时候就不需要额外的解析便能获得想要的结果。Parquet的灵感来自于2010年Google发表的Dremel论文,文中介绍了一种支持嵌套结构的存储格式,并且使用了列式存储的方式提升查询性能。Parquet仅仅是一种存储格式,它是语言、平台无关的,并且不需要和任何一种数据处理框架绑定。这也是parquet相较于orc的仅有优势:支持嵌套结构。Parquet 没有太多其他可圈可点的地方,比如他不支持update操作(数据写成后不可修改),不支持ACID等.
  11. SEQUENCEFILE:
  12. SequenceFile是Hadoop API 提供的一种二进制文件,它将数据以<key,value>的形式序列化到文件中。这种二进制文件内部使用Hadoop 的标准的Writable 接口实现序列化和反序列化。它与Hadoop API中的MapFile 是互相兼容的。Hive 中的SequenceFile 继承自Hadoop API 的SequenceFile,不过它的key为空,使用value 存放实际的值, 这样是为了避免MR 在运行map 阶段的排序过程。SequenceFile支持三种压缩选择:NONE, RECORD, BLOCK。 Record压缩率低,一般建议使用BLOCK压缩。 SequenceFile最重要的优点就是Hadoop原生支持较好,有API,但除此之外平平无奇,实际生产中不会使用。
  13. AVRO:
  14. Avro是一种用于支持数据密集型的二进制文件格式。它的文件格式更为紧凑,若要读取大量数据时,Avro能够提供更好的序列化和反序列化性能。并且Avro数据文件天生是带Schema定义的,所以它不需要开发者在API 级别实现自己的Writable对象。Avro提供的机制使动态语言可以方便地处理Avro数据。最近多个Hadoop 子项目都支持Avro 数据格式,如Pig 、Hive、Flume、Sqoop和Hcatalog。
复制代码
  Hive的四大常用存储格式存储服从及实行速度对比
  


   结论:ORCFILE存储文件读操纵服从最高
  耗时比力:ORC<arquet<RC<Text
  

   结论:ORCFILE存储文件占用空间少,压缩服从高
  占用空间:ORC<arquet<RC<Text
  4.3.1、创建表

  1. CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name
  2. [(col_name data_type [COMMENT col_comment], ...)]
  3. [COMMENT table_comment]
  4. [PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)]
  5. [CLUSTERED BY (col_name, col_name, ...)
  6. [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
  7. [ROW FORMAT row_format]
  8. [STORED AS file_format]
  9. [LOCATION hdfs_path]
  10. 字段解释说明:
  11. - CREATE TABLE
  12.         创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常。
  13. - EXTERNAL
  14.         关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION)
  15.         创建内部表时,会将数据移动到数据仓库指向的路径(默认位置);
  16.         创建外部表时,仅记录数据所在的路径,不对数据的位置做任何改变。
  17.         在删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。
  18. - COMMENT:
  19.         为表和列添加注释。
  20. - PARTITIONED BY
  21.         创建分区表
  22. - CLUSTERED BY
  23.         创建分桶表
  24. - SORTED BY
  25.         不常用
  26. - ROW FORMAT
  27.   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, ...)]
  28.         用户在建表的时候可以自定义SerDe或者使用自带的SerDe。
  29.         如果没有指定ROW FORMAT 或者ROW FORMAT DELIMITED,将会使用自带的SerDe。
  30.         在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的SerDe,Hive通过SerDe确定表的具体的列的数据。
  31.         SerDe是Serialize/Deserilize的简称,目的是用于序列化和反序列化。
  32. - STORED AS指定存储文件类型
  33.         常用的存储文件类型:SEQUENCEFILE(二进制序列文件)、TEXTFILE(文本)、RCFILE(列式存储格式文件)
  34.         如果文件数据是纯文本,可以使用STORED AS TEXTFILE。
  35.         如果数据需要压缩,使用 STORED AS SEQUENCEFILE。
  36. - LOCATION :
  37.         指定表在HDFS上的存储位置。
  38. - LIKE
  39.         允许用户复制现有的表结构,但是不复制数据。
复制代码
建表1:创建内部表(全部使用默认建表方式)

   当创建好表的时间,HDFS会在当前表所属的库中创建一个文件夹
  当设置表路径的时间,假如直接指向一个已有的路径,可以直接去使用文件夹中的数据
  当load数据的时间,就会将数据文件移动到到表对应的文件夹中
  而且数据一旦被load,就不能被修改
  我们查询数据也是查询文件中的文件,这些数据最终都会存放到HDFS
  当我们删除表的时间,表对应的文件夹会被删除,同时数据也会被删除
  默认建表的类型就是内部表
  1. #默认情况下使用的是default数据库
  2. #可以在切换到其它数据库:use bigdata30 该数据库在hdfs的具体位置/user/hive/warehouse/bigdata30.db
  3. #通过下面的语句创建students表后会在hdfs上生成一个students文件夹,文件夹里面是用来存储将来插入该表的students.txt数据(也可以是其他类型的文件)
  4. create table students
  5. (
  6.     id bigint,
  7.     name string,
  8.     age int,
  9.     gender string,
  10.     clazz string
  11. )
  12. ROW FORMAT DELIMITED FIELDS TERMINATED BY '_'; // 必选,指定列分隔符
  13. //使用load加载数据:
  14. load data inpath '/data/students.txt' into table students;
  15. 加载数据的作用就是将hdfs上的/data/students.txt的数据移动到/user/hive/warehouse/bigdata30.db/students文件夹下
  16. //使用上传文件的方式加载数据
  17. hadoop fs -put students.txt /user/hive/warehouse/bigdata30.db/students
  18. #在Hive中创建表时指定列分隔符是为了解析数据文件中的列。当Hive读取数据文件时,它会使用指定的列分隔符来识别和分隔每一列的数据。
  19. 表的路径为: /user/hive/warehouse/bigdata30.db/students
  20. 删除文件后数据和文件夹同时删除
复制代码
建表2:创建外部表

   ​ 外部表因为是指定其他的hdfs路径的数据加载到表中来,以是hive会认为自己不完全独占这份数据
  ​ 删除hive表的时间,数据仍然保存在hdfs中,不会删除。
  1. // 外部表(一般情况下,建一个与表名相同的文件夹,然后再将数据上传到该文件夹下,在创建表的时候指定location的路径为数据的存储路径即可)
  2. create external table students
  3. (
  4.     id bigint,
  5.     name string,
  6.     age int,
  7.     gender string,
  8.     clazz string
  9. )
  10. ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
  11. location '/data';
  12. //当指定的路径下有数据时,直接将数据加载到表中
  13. 表的存储路径hdfs://master:9000/data
  14. //当指定的路径下没有数据时,通过hadoop命令将数据上传到location指定的文件夹,数据自动加载到表中
  15. hadoop fs -put students.txt /data
  16. //也可以使用hive命令行中通过命令将本地文件导入到hdfs上
  17. hive> dfs -put /usr/local/soft/data/students.txt /data;
复制代码
建表3:指定存储格式

  1. create table IF NOT EXISTS students
  2. (
  3.     id bigint,
  4.     name string,
  5.     age int,
  6.     gender string,
  7.     clazz string
  8. )
  9. ROW FORMAT DELIMITED FIELDS TERMINATED BY ','
  10. STORED AS ORC
  11. // 指定储存格式为orcfile,inputFormat:RCFileInputFormat,outputFormat:RCFileOutputFormat,如果不指定,默认为textfile,
  12. 注意:除textfile以外,其他的存储格式的数据都不能直接加载,需要使用从表插入数据的方式。
  13. load data inpath '/data/students.txt' into table students;(不可用)
  14. insert into table students_test1 select * from students limit 10;(可用)
复制代码
建表4:使用查询语句建表 (这种方式比力常用)

  1. create table students1 as select * from students;
复制代码
建表5:只想建表,不需要加载数据

  1. create table students5 like students;
复制代码
  简单用户信息表创建:
  1. create table students6(
  2. id int,
  3. uname string,
  4. pwd string,
  5. gender string,
  6. age int
  7. )
  8. row format delimited fields terminated by ','
  9. lines terminated by '\n';
  10. 在Hive中,建表语句中的lines terminated by '\n'是可选的,并不是必须的。这个语句用于指定在加载数据时每行数据的结束符号,默认情况下,Hive会将每行数据以换行符 \n 作为结束标志。如果你的数据文件每行以换行符结束,你可以不用显式地指定这个参数,Hive会自动识别。但如果你的数据文件行结尾使用了其他分隔符,你就需要使用这个参数来告诉Hive如何正确地解析每行数据。
复制代码
  1. 1,admin,123456,nan,18
  2. 2,zhangsan,abc123,nan,23
  3. 3,lisi,654321,nv,16
复制代码
复杂人员信息表创建:
  1. create table IF NOT EXISTS t_person(
  2. name string,
  3. friends array<string>,
  4. children map<string,int>,
  5. address struct<street:string ,city:string>
  6. )
  7. row format delimited fields terminated by ',' -- 列与列之间的分隔符
  8. collection items terminated by '_' -- 集合数据类型元素与元素之间分隔符
  9. map keys terminated by ':' -- Map数据类型键与值之间的分隔符
  10. lines terminated by '\n';  -- 行与行之间的换行符
复制代码
  1. songsong,bingbing_lili,xiao song:18_xiaoxiao song:19,beng bu_anhui
  2. yangyang,caicai_susu,xiao yang:18_xiaoxiao yang:19,he fei_anhui
复制代码
4.3.2、加载数据

1、使用hdfs dfs -put '本地数据' 'hive表对应的HDFS目录下'

  1. hadoop fs -put /uer/local/soft/bigdata30/students.txt /data/students
复制代码
2、使用 load data

   注意:默认环境下加载的新数据会被追加到已有表的末尾,而不会覆盖或者清空已存在的数据
  1. load data inpath '/data/students.txt' into table students;
  2. // 清空表
  3. truncate table students;
  4. // 加上 local 关键字 可以将Linux本地目录下的文件 上传到 hive表对应HDFS 目录下 原文件不会被删除
  5. load data local inpath '/usr/local/soft/data/students.txt' into table students;
  6. // overwrite 覆盖加载
  7. load data local inpath '/usr/local/soft/data/students.txt' overwrite into table students;
复制代码
3、create table xxx as SQL语句

4、insert into table xxxx SQL语句 (没有as)

  1. // 将 students表的数据插入到students2 这是复制 不是移动 students表中的表中的数据不会丢失
  2. insert into table students1 select * from students;
  3. // 覆盖插入 把into 换成 overwrite
  4. insert overwrite table students1 select * from students;
复制代码
4.3.3、对表进行修改

   表现表
  1. //显示当前数据库下的所有表
  2. show tables;
  3. //显示当前数据库下以u开头的所有表
  4. show tables like 'u*';
  5. //查看表的结构(表的字段和字段类型)
  6. desc t_person;
  7. //查看表的详细结构,包括表的存储位置,表的存储类型,和表的一些其他的属性
  8. desc formatted students;
复制代码
  添加列
  1. alter table students2 add columns (education string);
复制代码
  更新列
  1. alter table stduents2 change education educationnew string;
  2. 这条语句将会更改 students2 表中名为 education 的列的数据类型为 STRING,同时将其列名更改为 educationnew。
复制代码
4.3.4、工作案例

   一样平常在公司中,使用外部表多一点,因为数据可以需要被多个步伐使用,避免误删,通常外部表会联合location一起使用
  外部表还可以将其他数据源中的数据 映射到 hive中,比如说:hbase,ElasticSearch…
  计划外部表的初志就是 让 表的元数据 与 数据 解耦
  第一步:在hdfs上创建表数据存储的文件夹

  1. hdfs dfs -mkdir -p /bigdata30/dept
  2. hdfs dfs -mkdir -p /bigdata30/emp
  3. hdfs dfs -mkdir -p /bigdata30/salgrade
复制代码
第二步:将数据上传到hdfs上

  1. hadoop fs -put /uer/local/soft/bigdata30/dept.txt /bigadta30/dept
  2. hadoop fs -put /uer/local/soft/bigdata30/dept.txt /bigadta30/emp
  3. hadoop fs -put /uer/local/soft/bigdata30/dept.txt /bigadta30/salgrade
复制代码
第三步:创建表

   创建dept表
  1. CREATE EXTERNAL TABLE IF NOT EXISTS dept (
  2.   DEPTNO int,
  3.   DNAME varchar(255),
  4.   LOC varchar(255)
  5. ) row format delimited fields terminated by ','
  6. location '/bigdata30/dept';
  7. 10,ACCOUNTING,NEW YORK
  8. 20,RESEARCH,DALLAS
  9. 30,SALES,CHICAGO
  10. 40,OPERATIONS,BOSTON
复制代码
  创建emp表
  1. CREATE EXTERNAL TABLE IF NOT EXISTS emp (
  2.    EMPNO int,
  3.    ENAME varchar(255),
  4.    JOB varchar(255),
  5.    MGR int,
  6.    HIREDATE date,
  7.    SAL decimal(10,0),
  8.    COMM decimal(10,0),
  9.    DEPTNO int
  10. ) row format delimited fields terminated by ','
  11. location '/bigdata30/emp';
  12. 7369,SMITH,CLERK,7902,1980-12-17,800,null,20
  13. 7499,ALLEN,SALESMAN,7698,1981-02-20,1600,300,30
  14. 7521,WARD,SALESMAN,7698,1981-02-22,1250,500,30
  15. 7566,JONES,MANAGER,7839,1981-04-02,2975,null,20
  16. 7654,MARTIN,SALESMAN,7698,1981-09-28,1250,1400,30
  17. 7698,BLAKE,MANAGER,7839,1981-05-01,2850,null,30
  18. 7782,CLARK,MANAGER,7839,1981-06-09,2450,null,10
  19. 7788,SCOTT,ANALYST,7566,1987-07-13,3000,null,20
  20. 7839,KING,PRESIDENT,null,1981-11-17,5000,null,10
  21. 7844,TURNER,SALESMAN,7698,1981-09-08,1500,0,30
  22. 7876,ADAMS,CLERK,7788,1987-07-13,1100,null,20
  23. 7900,JAMES,CLERK,7698,1981-12-03,950,null,30
  24. 7902,FORD,ANALYST,7566,1981-12-03,3000,null,20
  25. 7934,MILLER,CLERK,7782,1982-01-23,1300,null,10
复制代码
  创建salgrade表
  1. CREATE EXTERNAL TABLE IF NOT EXISTS salgrade (
  2.   GRADE int,
  3.   LOSAL int,
  4.   HISAL int
  5. ) row format delimited fields terminated by ','
  6. location '/bigdata30/salgrade';
  7. 1,700,1200
  8. 2,1201,1400
  9. 3,1401,2000
  10. 4,2001,3000
  11. 5,3001,9999
复制代码
4.3.5、Hive导出数据

   将表中的数据备份
  
  1. //创建存放数据的目录
  2. mkdir -p /usr/local/soft/shujia
  3. //导出查询结果的数据(导出到Node01上)
  4. insert overwrite local directory '/usr/local/soft/shujia' select * from t_person;
复制代码

  1. -- 创建存放数据的目录
  2. mkdir -p /usr/local/soft/shujia
  3. -- 导出查询结果的数据
  4. insert overwrite local directory '/usr/local/soft/shujia'
  5. ROW FORMAT DELIMITED fields terminated by ','
  6. collection items terminated by '-'
  7. map keys terminated by ':'
  8. lines terminated by '\n'
  9. select * from t_person;
复制代码

  1. -- 导出查询结果的数据
  2. insert overwrite local directory '/usr/local/soft/shujia'
  3. ROW FORMAT DELIMITED fields terminated by ','
  4. collection items terminated by '-'
  5. map keys terminated by ':'
  6. lines terminated by '\n'
  7. select * from t_person;-- 创建存放数据的目录
  8. hdfs dfs -mkdir -p /shujia/bigdata30/copy
  9. -- 导出查询结果的数据
  10. insert overwrite directory '/data/' ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' select clazz,count(1) from students group by clazz
复制代码

  1. // 创建存放数据的目录
  2. hdfs dfs -mkdir -p /bigdata30/data
  3. // 使用HDFS命令拷贝文件到其他目录
  4. hdfs dfs -cp /hive/warehouse/t_person/*  /bigdata30/data
复制代码

Hive分区与排序(内置函数)

1、Hive分区(十分重要!!)

   分区的目标:避免全表扫描,加快查询速度!
    在大数据中,最常见的一种思想就是分治,我们可以把大的文件切割分别成一个个的小的文件,如许每次操纵一个个小的文件就会很容易了,同样的原理,在hive当中也是支持这种思想的,就是我们可以把大的数据,按照天天或者每小时切分成一个个小的文件,如许去操纵小的文件就会容易很多了。
  假如现在我们公司一天产生3亿的数据量,那么为了方便管理和查询,就做以下的事变。
  ​ 1)建立分区(可按照日期,部门等等具体业务分区)
  ​ 2)分门别类的管理
  1.1 静态分区(SP)

   静态分区(SP)static partition–partition by (字段 类型)
  ​ 借助于物理的文件夹分区,实现快速检索的目标。
  ​ 一样平常对于查询比力频繁的列设置为分区列。
  ​ 加载数据的时间直接把对应分区中所有数据放到对应的文件夹中
    创建单分区表语法:
  1. CREATE TABLE IF NOT EXISTS t_student (
  2. sno int,
  3. sname string
  4. ) partitioned by(grade int)
  5. row format delimited fields terminated by ',';
  6. --  分区的字段不要和表的字段相同。相同会报错error10035
  7. 1,xiaohu01,1
  8. 2,xiaohu02,1
  9. 3,xiaohu03,1
  10. 4,xiaohu04,1
  11. 5,xiaohu05,1
  12. 6,xiaohu06,2
  13. 7,xiaohu07,2
  14. 8,xiaohu08,2
  15. 9,xiaohu09,3
  16. 10,xiaohu10,3
  17. 11,xiaohu11,3
  18. 12,xiaohu12,3
  19. 13,xiaohu13,3
  20. 14,xiaohu14,3
  21. 15,xiaohu15,3
  22. 16,xiaohu16,4
  23. 17,xiaohu17,4
  24. 18,xiaohu18,4
  25. 19,xiaohu19,4
  26. 20,xiaohu20,4
  27. 21,xiaohu21,4
  28. 22,xiaohu16,5
  29. 23,xiaohu17,4
  30. 24,xiaohu18,5
  31. 25,xiaohu19,5
  32. 26,xiaohu20,5
  33. 27,xiaohu21,5
  34. -- 载入数据
  35. -- 将相应年级的数据导入对应分区中(对应的是分区文件夹)
  36. --导入一年级的数据
  37. load data local inpath '/usr/local/soft/bigdata30/grade1.txt' into table t_student partition(grade=1);
  38. --导入二年级的数据
  39. load data local inpath '/usr/local/soft/bigdata30/grade2.txt' into table t_student partition(grade=2);
  40. -- 演示多拷贝一行上传,分区的列的值是分区的值,不是原来的值
复制代码
  静态多分区表语法:
  1. CREATE TABLE IF NOT EXISTS t_teacher (
  2. tno int,
  3. tname string
  4. ) partitioned by(grade int,clazz int)
  5. row format delimited fields terminated by ',';
  6. --注意:前后两个分区的关系为父子关系,也就是grade文件夹下面有多个clazz子文件夹。
  7. 1,xiaoge01,1,1
  8. 2,xiaoge02,1,1
  9. 3,xiaoge03,1,2
  10. 4,xiaoge04,1,2
  11. 5,xiaoge05,1,3
  12. 6,xiaoge06,1,3
  13. 7,xiaoge07,2,1
  14. 8,xiaoge08,2,1
  15. 9,xiaoge09,2,2
  16. --载入数据
  17. load data local inpath '/usr/local/soft/bigdata30/teacher_1.txt' into table t_teacher partition(grade=1,clazz=1);
  18. load data local inpath '/usr/local/soft/bigdata30/teacher_2.txt' into table t_teacher partition(grade=1,clazz=2);
复制代码
  分区表查询
  1. // 全表扫描,不推荐,效率低
  2. select count(*) from students_pt1;
  3. //查询分区表的数据
  4. select * from t_student where grade = 1;
  5. // 使用where条件进行分区裁剪,避免了全表扫描,效率高
  6. select count(*) from students_pt1 where grade = 1;
  7. // 也可以在where条件中使用非等值判断
  8. select count(*) from students_pt1 where grade<3 and grade>=1;
复制代码
  检察分区
  1. show partitions t_teacher;
复制代码
  添加分区
  1. alter table t_student add partition (grade=6);
  2. alter table t_teacher add partition (grade=3,clazz=1) location '/user/hive/warehouse/bigdata29.db/t_teacher/grade=3/clazz=1';
  3. location:表示hdfs上的分区路径(新添加在该表下的分区路径grade=3/clazz=1必须提前创建好)
复制代码
  删除分区
  1. alter table t_student drop partition (grade=5);
复制代码
1.3 动态分区(DP)


   开启动态分区首先要在hive会话中设置如下的参数
  1. # 表示开启动态分区
  2. hive> set hive.exec.dynamic.partition=true;
  3. # 表示动态分区模式:strict(需要配合静态分区一起使用)、nostrict
  4. # strict: insert into table students_pt partition(dt='anhui',pt) select ......,pt from students;
  5. hive> set hive.exec.dynamic.partition.mode=nonstrict;
  6. ===================以下是可选参数======================
  7. # 表示支持的最大的分区数量为1000,可以根据业务自己调整
  8. hive> set hive.exec.max.dynamic.partitions.pernode=1000;
复制代码
  其余的参数详细配置如下
  1. 设置为true表示开启动态分区的功能(默认为false)
  2. --hive.exec.dynamic.partition=true;
  3. 设置为nonstrict,表示允许所有分区都是动态的(默认为strict)
  4. -- hive.exec.dynamic.partition.mode=nonstrict;
  5. -- hive.exec.dynamic.partition.mode=strict;
  6. 每个mapper或reducer可以创建的最大动态分区个数(默认为100)
  7. 比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错
  8. --hive.exec.max.dynamic.partition.pernode=100;
  9. 一个动态分区创建可以创建的最大动态分区个数(默认值1000)
  10. --hive.exec.max.dynamic.partitions=1000;
  11. 全局可以创建的最大文件个数(默认值100000)
  12. --hive.exec.max.created.files=100000;
  13. 当有空分区产生时,是否抛出异常(默认false)
  14. -- hive.error.on.empty.partition=false;  
复制代码

  1. --创建外部表
  2. CREATE EXTERNAL TABLE IF NOT EXISTS t_student_e (
  3. sno int,
  4. sname string,
  5. grade int,
  6. clazz int
  7. )
  8. row format delimited fields terminated by ','
  9. location "/bigdata30/teachers";
  10. --创建分区表
  11. CREATE TABLE IF NOT EXISTS t_student_d (
  12. sno int,
  13. sname string
  14. ) partitioned by (grade int,clazz int)
  15. row format delimited fields terminated by ',';
复制代码
  1. 数据:
  2. 1,xiaohu01,1,1
  3. 2,xiaohu02,1,1
  4. 3,xiaohu03,1,1
  5. 4,xiaohu04,1,2
  6. 5,xiaohu05,1,2
  7. 6,xiaohu06,2,3
  8. 7,xiaohu07,2,3
  9. 8,xiaohu08,2,3
  10. 9,xiaohu09,3,3
  11. 10,xiaohu10,3,3
  12. 11,xiaohu11,3,3
  13. 12,xiaohu12,3,4
  14. 13,xiaohu13,3,4
  15. 14,xiaohu14,3,4
  16. 15,xiaohu15,3,4
  17. 16,xiaohu16,4,4
  18. 17,xiaohu17,4,4
  19. 18,xiaohu18,4,5
  20. 19,xiaohu19,4,5
  21. 20,xiaohu20,4,5
  22. 21,xiaohu21,4,5
复制代码
  假如静态分区的话,我们插入数据必须指定分区的值。
  假如想要插入多个班级的数据,我要写很多SQL而且实行24次很麻烦。
  而且静态分区有可能会产生数据错误问题
  1. -- 会报错
  2. insert overwrite table t_student_d partition (grade=1,clazz=1) select * from t_student_e;
复制代码
  假如使用动态分区,动态分区会根据select的结果自动判断数据应该load到哪儿分区去。
  1. insert overwrite table t_student_d partition (grade,clazz) select * from t_student_e;
复制代码
  长处:不用手动指定了,自动会对数据进行分区
  缺点:可能会出现数据倾斜
  2、Hive分桶

2.1 业务场景

   数据分桶的实用场景:

  ​ 分区提供了一个隔离数据和优化查询的便利方式,不过并非所有的数据都可形成合理的分区,尤其是需要确定符合巨细的分区分别方式
​ 不合理的数据分区分别方式可能导致有的分区数据过多,而某些分区没有什么数据的尴尬环境
​ 分桶是将数据集分解为更容易管理的多少部门的另一种技术。
​ 分桶就是将数据按照字段进行分别,可以将数据按照字段分别到多个文件当中去。(都各不相同)
  2.2 数据分桶原理


2.3 数据分桶优势

   方便抽样
  ​ 使取样(sampling)更高效。在处置惩罚大规模数据集时,在开发和修改查询的阶段,假如能在数据集的一小部门数据上试运行查询,会带来很多方便
  进步join查询服从
  ​ 得到更高的查询处置惩罚服从。桶为表加上了额外的布局,Hive 在处置惩罚有些查询时能利用这个布局。具体而言,连接两个在(包罗连接列的)相同列上分别了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操纵。对于JOIN操纵两个表有一个相同的列,假如对这两个表都进行了桶操纵。那么将保存相同列值的桶进行JOIN操纵就可以,可以大大较少JOIN的数据量。
  2.4 分桶实战

   ​ 首先,分区和分桶是两个不同的概念,很多资料上说需要先分区在分桶,实在不然,分区是对数据进行分别,而分桶是对文件进行分别。
  ​ 当我们的分区之后,末了的文件还是很大怎么办,就引入了分桶的概念。
  将这个比力大的文件再分成多少个小文件进行存储,我们再去查询的时间,在这个小范围的文件中查询就会快很多。
  ​ 对于hive中的每一张表、分区都可以进一步的进行分桶。
  ​ 当然,分桶不是说将文件随机进行切分存储,而是有规律的进行存储。在看完下面的例子后进行表明,现在干巴巴的表明也不太好理解。它是由列的哈希值除以桶的个数来决定每条数据分别在哪个桶中。
  创建顺序和分区一样,创建的方式不一样。
    首先我们需要开启分桶的支持
  1. (依然十分重要,不然无法进行分桶操作!!!!)
  2. set hive.enforce.bucketing=true;
复制代码
  数据预备(id,name,age)
  1. 1,tom,11
  2. 2,cat,22
  3. 3,dog,33
  4. 4,hive,44
  5. 5,hbase,55
  6. 6,mr,66
  7. 7,alice,77
  8. 8,scala,88
复制代码
  创建一个普通的表
  1. create table person
  2. (
  3. id int,
  4. name string,
  5. age int
  6. )
  7. row format delimited
  8. fields terminated by ',';
复制代码
  将数据load到这张表中
  1. load data local inpath '文件在Linux上的绝对路径' into table person ;
复制代码
  创建分桶表
  1. create table psn_bucket
  2. (
  3. id int,
  4. name string,
  5. age int
  6. )
  7. clustered by(age) into 4 buckets
  8. row format delimited fields terminated by ',';
复制代码
  将数据insert到表psn_bucket中
  (注意:这里和分区表插入数据有所区别,分区表需要select 和指定分区,而分桶则不需要)
  1. insert into psn_bucket select * from person;
复制代码
  在HDFS上检察数据
  

   查询数据
  我们在linux中使用Hadoop的命令检察一下(与我们料想的顺序一致)
  1. hadoop fs -cat /user/hive/warehouse/bigdata30.db/psn_bucket/*
复制代码
  这里设置的桶的个数是4 数据按照 年龄%4 进行放桶(文件)
11%4 == 3 -----> 000003_0
22%4 == 2 -----> 000002_0
33%4 == 1 -----> 000001_0
44%4 == 0 -----> 000000_0
…以此类推
  3、Hive JDBC

启动hiveserver2

  1. nohup hiveserver2 &
  2. 或者
  3. hiveserver2 &
复制代码
新建maven项目并添加两个依赖

  1.     <dependency>
  2.         <groupId>org.apache.hadoop</groupId>
  3.         <artifactId>hadoop-common</artifactId>
  4.         <version>2.7.6</version>
  5.     </dependency>
  6.     <!-- https://mvnrepository.com/artifact/org.apache.hive/hive-jdbc -->
  7.     <dependency>
  8.         <groupId>org.apache.hive</groupId>
  9.         <artifactId>hive-jdbc</artifactId>
  10.         <version>1.2.1</version>
  11.     </dependency>
复制代码
编写JDBC代码

  1. import java.sql.*;
  2. public class HiveJDBC {
  3.     public static void main(String[] args) throws ClassNotFoundException, SQLException {
  4.         Class.forName("org.apache.hive.jdbc.HiveDriver");
  5.         Connection conn = DriverManager.getConnection("jdbc:hive2://master:10000/bigdata29");
  6.         Statement stat = conn.createStatement();
  7.         ResultSet rs = stat.executeQuery("select * from students limit 10");
  8.         while (rs.next()) {
  9.             int id = rs.getInt(1);
  10.             String name = rs.getString(2);
  11.             int age = rs.getInt(3);
  12.             String gender = rs.getString(4);
  13.             String clazz = rs.getString(5);
  14.             System.out.println(id + "," + name + "," + age + "," + gender + "," + clazz);
  15.         }
  16.         rs.close();
  17.         stat.close();
  18.         conn.close();
  19.     }
  20. }
复制代码
4、Hive的4种排序


4.1 全局排序


  1. select * from 表名 order by 字段名1[,别名2...];
复制代码
4.2 局部排序(对reduce内部做排序)


  1. set mapreduce.job.reduces=3;
复制代码

  1. set mapreduce.job.reduces;
复制代码

  1. select * from 表名 sort by 字段名[,字段名...];
复制代码
4.3 分区排序(本身没有排序)

   distribute by(字段)根据指定的字段将数据分到不同的reducer,且分发算法是hash散列。
  雷同MR中partition,进行分区,联合sort by使用。(注意:distribute by 要在sort by之前)
  对于distrbute by 进行测试,一定要多分配reduce进行处置惩罚,否则无法看到distribute by的结果。
  设置reduce个数
  1. set mapreduce.job.reduce=7;
复制代码

  1. select * from 表名 distribute by 字段名[,字段名...] sort by 字段;
复制代码
4.3 分区并排序


  1. select * from 表名 cluster by 字段名[,字段名...];
  2. select * from 表名 distribute by 字段名[,字段名...] sort by 字段名[,字段名...];
复制代码
5、Hive内置函数

  1. https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
复制代码
  1. -- 1.查看系统自带函数
  2. show functions;
  3. -- 2.显示自带的函数的用法
  4. desc function xxxx;
  5. -- 3.详细显示自带的函数的用法
  6. desc function extended upper;
复制代码
5.1 内置函数分类

  1. 关系操作符:包括 = 、 <> 、 <= 、>=等
  2. 算数操作符:包括 + 、 - 、 *、/等
  3. 逻辑操作符:包括AND 、 && 、 OR 、 || 等
  4. 复杂类型构造函数:包括map、struct、create_union等
  5. 复杂类型操作符:包括A[n]、Map[key]、S.x
  6. 数学操作符:包括ln(double a)、sqrt(double a)等
  7. 集合操作符:包括size(Array)、sort_array(Array)等
  8. 类型转换函数: binary(string|binary)、cast(expr as )
  9. 日期函数:包括from_unixtime(bigint unixtime[, string format])、unix_timestamp()等
  10. 条件函数:包括if(boolean testCondition, T valueTrue, T valueFalseOrNull)等
  11. 字符串函数:包括acat(string|binary A, string|binary B…)等
  12. 其他:xpath、get_json_objectscii(string str)、con
复制代码
5.2 UDTF hive中特殊的一个功能(进一出多)

  1. -- UDF 进一出一
  2. -- UDAF 进多出一
  3. -- collect_set()和collect_list()将多行数据转成一行,区别就是list里面可重复而set里面是去重的
  4. -- concat_ws(':',collect_set(type))   ':' 表示你合并后用什么分隔,collect_set(stage)表示要合并表中的那一列数据
  5. select 字段名,concat_ws(':',collect_set(列名)) as 别名 from 表名 group by id;
  6. -- UDTF 进一出多
  7. -- explode  可以将一行数据变成多行数据
  8. select  explode(split(列名,"数据的分隔符")) from 表名;
  9. -- lateral view 表生成函数,可以将explode的数据生成一个列表
  10. select id,name,列名 from 表1,lateral view explode(split(表1.列名,"数据的分隔符"))新列名 as 别列名;
  11. --注意:collect_set() 和 collect_list() 是 Hive 中用于聚合操作的集合函数,它们分别用于将列值聚合成集合或列表。
复制代码
  1. -- 创建数据库表
  2. create table t_movie1(
  3. id int,
  4. name string,
  5. types string
  6. )
  7. row format delimited fields terminated by ','
  8. lines terminated by '\n';
  9. -- 电影数据  movie1.txt
  10. -- 加载数据到数据库 load data inpath '/shujia/movie1.txt' into table t_movie1;
  11. 1,这个杀手不太冷,剧情-动作-犯罪
  12. 2,七武士,动作-冒险-剧情
  13. 3,勇敢的心,动作-传记-剧情-历史-战争
  14. 4,东邪西毒,剧情-动作-爱情-武侠-古装
  15. 5,霍比特人,动作-奇幻-冒险
  16. -- explode  可以将一组数组的数据变成一列表
  17. select  explode(split(types,"-")) from t_movie1;
  18. -- lateral view 表生成函数,可以将explode的数据生成一个列表
  19. select id,name,type from t_movie1 lateral view explode(split(types,"-")) typetable as type;
复制代码
  1. -- 创建数据库表
  2. create table t_movie2(
  3. id int,
  4. name string,
  5. type string
  6. )
  7. row format delimited fields terminated by ','
  8. lines terminated by '\n';
  9. -- 电影数据 movie2.txt
  10. -- 加载数据到数据库 load data inpath '/shujia/movie2.txt' into table t_movie2;                                    1,这个杀手不太冷,剧情
  11. 1,这个杀手不太冷,动作
  12. 1,这个杀手不太冷,犯罪
  13. 2,七武士,动作
  14. 2,七武士,冒险
  15. 2,七武士,剧情
  16. 3,勇敢的心,动作
  17. 3,勇敢的心,传记
  18. 3,勇敢的心,剧情
  19. 3,勇敢的心,历史
  20. 3,勇敢的心,战争
  21. 4,东邪西毒,剧情
  22. 4,东邪西毒,动作
  23. 4,东邪西毒,爱情
  24. 4,东邪西毒,武侠
  25. 4,东邪西毒,古装
  26. 5,霍比特人,动作
  27. 5,霍比特人,奇幻
  28. 5,霍比特人,冒险
  29. -- collect_set()和collect_list()都是对列转成行,区别就是list里面可重复而set里面是去重的
  30. -- concat_ws(':',collect_set(type))   ':' 表示你合并后用什么分隔,collect_set(stage)表示要合并表中的那一列数据
  31. select id,concat_ws(':',collect_set(type)) as types from t_movie2 group by id;
复制代码
5.3 WordCount案例

   数据预备
  1. hello,world
  2. hello,bigdata
  3. like,life
  4. bigdata,good
复制代码
  建表
  1. create table wc2
  2. (
  3. line string
  4. )
  5. row format delimited fields terminated by '\n'
复制代码
  导入数据
  1. load data local inpath '/usr/local/soft/data/wc1.txt' into table wc;
复制代码
  步骤1:先对一行数据进行切分
  1. select split(line,',') from wc;
复制代码
  步骤2:将行转列
  1. select explode(split(line,',')) from wc;
复制代码
  步骤3:将相同的进行分组统计
  1. select w.word,count(*) from (select explode(split(line,',')) as word from wc) w group by w.word;
复制代码
Hive函数学习

1、count(*)、count(1) 、count(‘字段名’) 区别

   从实行结果来看
  
  从实行服从来看
  
  在工作中假如没有特殊的要求,就使用count(1)来进行计数。
  2、hive语句的实行顺序

1.from
2.join on 或 lateral view explode(需炸裂的列) tbl as 炸裂后的列名
3.where
4.group by
5.聚合函数 如Sum() avg() count(1)等
6.having 在此开始可以使用select中的别名
7.select 若包罗over()开窗函数,此时select中的内容作为窗口函数的输入,窗口中所选的数据范围也是在group by,having之后,并不是针对where后的数据进行开窗,这点要注意。需要注意开窗函数的实行顺序及时间点。
8.distinct
9.order by
10.limit(发起:以后在大数据环境中,一张表的数据量肯定十分庞大的,养成加limit的风俗)
   where 条件里不支持不等式子查询,实际上是支持 in、not in、exists、not exists( hive3.x版本是支持的 )
  1. # 查询薪资大于SCOTT的薪资员工信息
  2. -- 列出与“SCOTT”从事相同工作的所有员工。
  3. select  t1.EMPNO
  4.         ,t1.ENAME
  5.         ,t1.JOB
  6. from emp t1
  7. where t1.ENAME != "SCOTT" and t1.job in(
  8.     select  job
  9.     from emp
  10.     where ENAME = "SCOTT");
  11.    
  12. 7900,JAMES,CLERK,7698,1981-12-03,950,null,30
  13. 7902,FORD,ANALYST,7566,1981-12-03,3000,null,20
  14. select  t1.EMPNO
  15.         ,t1.ENAME
  16.         ,t1.JOB
  17. from emp t1
  18. where t1.ENAME != "SCOTT" and exists(
  19.     select  job
  20.     from emp t2
  21.     where ENAME = "SCOTT"
  22.     and t1.job = t2.job
  23. );
复制代码
4、hive中巨细写不敏感(列名无所谓巨细写
5、在hive中,数据中假如有null字符串,加载到表中的时间会变成 null (不是字符串)
   假如需要判断 null,使用 某个字段名 is null 如许的方式来判断
  或者使用 nvl() 函数,不能 直接 某个字段名 == null
  6、使用explain检察SQL实行计划
   口试题:hive中一条sql语句如何剖析成MapReduce作业实行的?(hive的版本)
  1. explain select  t1.EMPNO
  2.         ,t1.ENAME
  3.         ,t1.JOB
  4. from emp t1
  5. where t1.ENAME != "SCOTT" and t1.job in(
  6.     select  job
  7.     from emp
  8.     where ENAME = "SCOTT");
  9.    
  10. # 查看更加详细的执行计划,加上extended
  11. explain extended select  t1.EMPNO
  12.         ,t1.ENAME
  13.         ,t1.JOB
  14. from emp t1
  15. where t1.ENAME != "SCOTT" and t1.job in(
  16.     select  job
  17.     from emp
  18.     where ENAME = "SCOTT");
复制代码
3、Hive 常用函数

3.1、关系运算

  1. // 等值比较 = == < = >
  2. // 不等值比较 != <>
  3. // 区间比较: select * from default.students where id between 1500100001 and 1500100010;
  4. // 空值/非空值判断:isnull、isnotnull、nvl()、isnull()
  5. // like、rlike、regexp用法
复制代码
3.2、数值计算

  1. 取整函数(四舍五入):round
  2. 向上取整:ceil
  3. 向下取整:floor
复制代码
3.3、条件函数(主要使用场景是数据洗濯的过程中使用,有些构建表的过程也是需要的)


  1. create table sc(
  2. sno string,
  3. cno string,
  4. score bigint
  5. )row format delimited fields terminated by '\n';
  6. select sal,if(sal<2000,'低薪',if(sal>=2000 and sal<3000,'中等','高薪')) as level from emp;
  7. select if(1>0,1,0);
  8. select if(1>0,if(-1>0,-1,1),0);
  9. select score,if(score>120,'优秀',if(score>100,'良好',if(score>90,'及格','不及格'))) as pingfen from sc;
复制代码

  1. select COALESCE(null,'1','2'); // 1 从左往右 依次匹配 直到非空为止
  2. select COALESCE('1',null,'2'); // 1
复制代码

  1. select sal,case when sal<2000 then '低薪'
  2.                 when sal>=2000 and sal<3000 then '中等薪资'
  3.                 else '高薪' end as level
  4. from emp;
  5. select  score
  6.         ,case when score>90 then '优秀'
  7.               when score>80 then '良好'
  8.               when score>=60 then '及格'
  9.         else '不及格'
  10.         end as pingfen
  11. from sc;
  12. select  name
  13.         ,case name when "施笑槐" then "槐ge"
  14.                   when "吕金鹏" then "鹏ge"
  15.                   when "单乐蕊" then "蕊jie"
  16.         else "算了不叫了"
  17.         end as nickname
  18. from students limit 10;
复制代码
  注意条件的顺序
  3.4、日期函数重点!!!

  1. select from_unixtime(1717666208,'YYYY年MM月dd日 hh时mm分ss秒');
  2. select from_unixtime(unix_timestamp(),'YYYY/MM/dd HH:mm:ss');
  3. // '2021年01月14日' -> '2021-01-14'
  4. select from_unixtime(unix_timestamp('2024年06月06日','yyyy年MM月dd日'),'yyyy-MM-dd');
  5. // "04牛2021数加16强" -> "2021/04/16"
  6. select from_unixtime(unix_timestamp("04牛2024数加11强","MM牛yyyy数加dd强"),"yyyy年MM月dd日");
复制代码
3.5、字符串函数

  1. concat('123','456'); // 123456
  2. concat('123','456',null); // NULL
  3. select concat_ws('#','a','b','c'); // a#b#c
  4. select concat_ws('#','a','b','c',NULL); // a#b#c 可以指定分隔符,并且会自动忽略NULL
  5. select concat_ws("|",cast(id as string),name,cast(age as string),gender,clazz) from students limit 10;
  6. select substring("abcdefg",1); // abcdefg HQL中涉及到位置的时候 是从1开始计数
  7. // '2021/01/14' -> '2021-01-14'
  8. select concat_ws("-",substring('2021/01/14',1,4),substring('2021/01/14',6,2),substring('2021/01/14',9,2));
  9. // 建议使用日期函数去做日期
  10. select from_unixtime(unix_timestamp('2021/01/14','yyyy/MM/dd'),'yyyy-MM-dd');
  11. select split("abcde,fgh",","); // ["abcde","fgh"]
  12. select split("a,b,c,d,e,f",",")[2]; // c 数组的下标依旧是从0开始
  13. select explode(split("abcde,fgh",",")); // abcde
  14.                                                                                 //  fgh
  15. // 解析json格式的数据
  16. select get_json_object('{"name":"zhangsan","age":18,"score":[{"course_name":"math","score":100},{"course_name":"english","score":60}]}',"$.score[0].score"); // 60
  17. {
  18.         "name": "zhangsan",
  19.         "age": 18,
  20.         "score": [{
  21.                 "course_name": "math",
  22.                 "score": 100
  23.         }, {
  24.                 "course_name": "english",
  25.                 "score": 60
  26.         }]
  27. }
  28. $.score[0].score
复制代码
3.6、例题:Hive 中的wordCount

  1. create table words(
  2.     words string
  3. )row format delimited fields terminated by '\n';
  4. // 数据
  5. hello,java,hello,java,scala,python
  6. hbase,hadoop,hadoop,hdfs,hive,hive
  7. hbase,hadoop,hadoop,hdfs,hive,hive
  8. select word,count(*) from (select explode(split(words,',')) word from words) a group by a.word;
  9. // 结果
  10. hadoop        4
  11. hbase        2
  12. hdfs        2
  13. hello        2
  14. hive        4
  15. java        2
  16. python        1
  17. scala        1
复制代码
3.7、Hive窗口函数

   普通的聚合函数每组(Group by)只返回一个值,而开窗函数则可为窗口中的每行都返回一个值。
简单理解,就是对查询的结果多出一列,这一列可以是聚合值,也可以是排序值。
开窗函数一样平常就是说的是over()函数,其窗口是由一个 OVER 子句 定义的多行记录
开窗函数一样平常分为两类,聚合开窗函数和排序开窗函数。
  1. -- 聚合格式
  2. select sum(字段名) over([partition by 字段名] [ order by 字段名]) as 别名,
  3.         max(字段名) over() as 别名
  4. from 表名;
  5. -- 排序窗口格式
  6. select rank() over([partition by 字段名] [ order by 字段名]) as 别名 from 表名;
复制代码
注意点:

   测试数据
  1. -- 创建表
  2. create table t_fraction(
  3. name string,
  4. subject string,
  5. score int)
  6. row format delimited fields terminated by ","
  7. lines terminated by '\n';
  8. -- 测试数据 fraction.txt
  9. 孙悟空,语文,10
  10. 孙悟空,数学,73
  11. 孙悟空,英语,15
  12. 猪八戒,语文,10
  13. 猪八戒,数学,73
  14. 猪八戒,英语,11
  15. 沙悟净,语文,22
  16. 沙悟净,数学,70
  17. 沙悟净,英语,31
  18. 唐玄奘,语文,21
  19. 唐玄奘,数学,81
  20. 唐玄奘,英语,23
  21. -- 上传数据
  22. load data local inpath '/usr/local/soft/bigdata17/xiaohu/data/fraction.txt' into table t_fraction;
复制代码
3.7.1、 聚合开窗函数

   sum(求和)
  min(最小)
  max(最大)
  avg(平均值)
  count(计数)
  lag(获取当前行上一行的数据)
  lead(获取当前行下一行的数据)
  1. --
  2. select name,subject,score,sum(score) over() as sumover from t_fraction;
  3. +-------+----------+--------+----------+
  4. | name  | subject  | score  | sumover  |
  5. +-------+----------+--------+----------+
  6. | 唐玄奘   | 英语       | 23     | 321      |
  7. | 唐玄奘   | 数学       | 81     | 321      |
  8. | 唐玄奘   | 语文       | 21     | 321      |
  9. | 沙悟净   | 英语       | 31     | 321      |
  10. | 沙悟净   | 数学       | 12     | 321      |
  11. | 沙悟净   | 语文       | 22     | 321      |
  12. | 猪八戒   | 英语       | 11     | 321      |
  13. | 猪八戒   | 数学       | 73     | 321      |
  14. | 猪八戒   | 语文       | 10     | 321      |
  15. | 孙悟空   | 英语       | 15     | 321      |
  16. | 孙悟空   | 数学       | 12     | 321      |
  17. | 孙悟空   | 语文       | 10     | 321      |
  18. +-------+----------+--------+----------+
  19. select name,subject,score,
  20. sum(score) over() as sum1,
  21. sum(score) over(partition by subject) as sum2,
  22. sum(score) over(partition by subject order by score) as sum3,
  23. -- 由起点到当前行的窗口聚合,和sum3一样
  24. sum(score) over(partition by subject order by score rows between unbounded preceding and current row) as sum4,
  25. -- 当前行和前面一行的窗口聚合
  26. sum(score) over(partition by subject order by score rows between 1 preceding and current row) as sum5,
  27. -- 当前行的前面一行到后面一行的窗口聚合  前一行+当前行+后一行
  28. sum(score) over(partition by subject order by score rows between 1 preceding and 1 following) as sum6,
  29. -- 当前行与后一行之和
  30. sum(score) over(partition by subject order by score rows between current row and 1 following) as sum6,
  31. -- 当前和后面所有的行
  32. sum(score) over(partition by subject order by score rows between current row and unbounded following) as sum7
  33. from t_fraction;
  34. rows:行
  35. unbounded preceding:起点
  36. unbounded following:终点
  37. n preceding:前 n 行
  38. n following:后 n 行
  39. current row:当前行
  40. +-------+----------+--------+-------+-------+-------+-------+-------+-------+-------+
  41. | name  | subject  | score  | sum1  | sum2  | sum3  | sum4  | sum5  | sum6  | sum7  |
  42. +-------+----------+--------+-------+-------+-------+-------+-------+-------+-------+
  43. | 孙悟空   | 数学       | 12     | 359   | 185   | 12    | 12    | 12    | 31    | 185   |
  44. | 沙悟净   | 数学       | 19     | 359   | 185   | 31    | 31    | 31    | 104   | 173   |
  45. | 猪八戒   | 数学       | 73     | 359   | 185   | 104   | 104   | 92    | 173   | 154   |
  46. | 唐玄奘   | 数学       | 81     | 359   | 185   | 185   | 185   | 154   | 154   | 81    |
  47. | 猪八戒   | 英语       | 11     | 359   | 80    | 11    | 11    | 11    | 26    | 80    |
  48. | 孙悟空   | 英语       | 15     | 359   | 80    | 26    | 26    | 26    | 49    | 69    |
  49. | 唐玄奘   | 英语       | 23     | 359   | 80    | 49    | 49    | 38    | 69    | 54    |
  50. | 沙悟净   | 英语       | 31     | 359   | 80    | 80    | 80    | 54    | 54    | 31    |
  51. | 孙悟空   | 语文       | 10     | 359   | 94    | 10    | 10    | 10    | 31    | 94    |
  52. | 唐玄奘   | 语文       | 21     | 359   | 94    | 31    | 31    | 31    | 53    | 84    |
  53. | 沙悟净   | 语文       | 22     | 359   | 94    | 53    | 53    | 43    | 84    | 63    |
  54. | 猪八戒   | 语文       | 41     | 359   | 94    | 94    | 94    | 63    | 63    | 41    |
  55. +-------+----------+--------+-------+-------+-------+-------+-------+-------+-------+
复制代码
rows必须跟在Order by 子句之后,对排序的结果进行限定,使用固定的行数来限定分区中的数据行数量。
   **OVER():**指定分析函数工作的数据窗口巨细,这个数据窗口巨细可能会随着行的变而变化。
  **CURRENT ROW:**当前行
  **n PRECEDING:**往前n行数据
  **n FOLLOWING:**往后n行数据
  **UNBOUNDED:**起点,UNBOUNDED PRECEDING 表现从前面的起点, UNBOUNDED FOLLOWING表现到后面的终点
  **LAG(col,n,default_val):**往前第n行数据,col是列名,n是往上的行数,当第n行为null的时间取default_val
  **LEAD(col,n, default_val):**往后第n行数据,col是列名,n是往下的行数,当第n行为null的时间取default_val
  **NTILE(n):**把有序分区中的行分发到指定命据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。
  cume_dist(),计算某个窗口或分区中某个值的累积分布。假定升序排序,则使用以下公式确定累积分布:
  ​ 小于即是当前值x的行数 / 窗口或partition分区内的总行数。其中,x 即是 order by 子句中指定的列的当前行中的值。
  聚合开窗函数实战:

实战1:Hive用户购买明细数据分析

   创建表和加载数据
  1. name,orderdate,cost
  2. jack,2017-01-01,10
  3. tony,2017-01-02,15
  4. jack,2017-02-03,23
  5. tony,2017-01-04,29
  6. jack,2017-01-05,46
  7. jack,2017-04-06,42
  8. tony,2017-01-07,50
  9. jack,2017-01-08,55
  10. mart,2017-04-08,62
  11. mart,2017-04-09,68
  12. neil,2017-05-10,12
  13. mart,2017-04-11,75
  14. neil,2017-06-12,80
  15. mart,2017-04-13,94
  16. 建表加载数据
  17. vim business.txt
  18. create table business
  19. (
  20. name string,
  21. orderdate string,
  22. cost int
  23. )ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';
  24. load data local inpath "/shujia/bigdata17/xiaohu/data/business.txt" into table business;
复制代码
实战1需求:

   需求1:查询在2017年4月份购买过的顾客及总人数
  1. # 分析:按照日期过滤、分组count求总人数
  2. select t1.name,t1.orderdate,count(1) over() as counts_04 from (select name,orderdate from business where month(orderdate)='04') t1;
复制代码
  需求2:查询顾客的购买明细及月购买总额
  1. # 分析:按照顾客分组、sum购买金额
  2. select name,orderdate,cost,sum(cost) over(partition by name,month(orderdate))  from business;
复制代码
  需求3:上述的场景,要将cost按照日期进行累加
  1. # 分析:按照顾客分组、日期升序排序、组内每条数据将之前的金额累加
  2. select name,orderdate,cost,sum(cost) over(partition by name order by orderdate rows between unbounded preceding and current row)  from business;
复制代码
  需求4:查询顾客上次的购买时间
  1. ·# 分析:查询出明细数据同时获取上一条数据的购买时间(肯定需要按照顾客分组、时间升序排序)
  2. select name,orderdate,cost,lag(orderdate,1) over(partition by name order by orderdate) as last_time from business;
复制代码
  需求5:查询前20%时间的订单信息
  1. 分析:按照日期升序排序、取前20%的数据
  2. select t1.name,t1.orderdate,t1.cost from (select name,orderdate,cost,ntile(5) over(order by orderdate) as n from business) t1 where t1.n=1;
复制代码
3.7.2、 排序开窗函数(重点)


  1. select name,subject,
  2. score,
  3. rank() over(partition by subject order by score desc) rp,
  4. dense_rank() over(partition by subject order by score desc) drp,
  5. row_number() over(partition by subject order by score desc) rnp,
  6. percent_rank() over(partition by subject order by score) as percent_rank
  7. from t_fraction;
复制代码
  1. select name,subject,score,
  2. rank() over(order by score) as row_number,
  3. percent_rank() over(partition by subject order by score) as percent_rank
  4. from t_fraction;
复制代码
实战2:Hive分析学天生绩信息

   创建表语加载数据
  1. name        subject        score
  2. 李毅        语文        87
  3. 李毅        数学        95
  4. 李毅        英语        68
  5. 黄仙        语文        94
  6. 黄仙        数学        56
  7. 黄仙        英语        84
  8. 小虎        语文        64
  9. 小虎        数学        86
  10. 小虎        英语        84
  11. 许文客        语文        65
  12. 许文客        数学        85
  13. 许文客        英语        78
  14. 建表加载数据
  15. vim score.txt
  16. create table score2
  17. (
  18. name string,
  19. subject string,
  20. score int
  21. ) row format delimited fields terminated by "\t";
  22. load data local inpath '/shujia/bigdata17/xiaohu/data/score.txt' into table score;
复制代码
  需求1:每门学科学天生绩排名(是否并列排名、空位排名三种实现)
  1. 分析:学科分组、成绩降序排序、按照成绩排名
  2. select name,subject,score,
  3. rank() over(partition by subject order by score desc) rp,
  4. dense_rank() over(partition by subject order by score desc) drp,
  5. row_number() over(partition by subject order by score desc) rmp
  6. from
  7. score;
复制代码
  需求2:每门学科成绩排名top 2的学生
  1. select t1.name,t1.subject,t1.score from (select name,subject,score,row_number() over(partition by subject order by score desc) as rn from score2) t1 where t1.rn<3;
复制代码
4、Hive 行转列

lateral view explode
  1. create table testArray2(
  2.     name string,
  3.     weight array<string>
  4. )row format delimited
  5. fields terminated by '\t'
  6. COLLECTION ITEMS terminated by ',';
  7. 小虎        "150","170","180"
  8. 火火        "150","180","190"
  9. select name,col1  from testarray2 lateral view explode(weight) t1 as col1;
  10. 小虎        150
  11. 小虎        170
  12. 小虎        180
  13. 火火        150
  14. 火火        180
  15. 火火        190
  16. select key from (select explode(map('key1',1,'key2',2,'key3',3)) as (key,value)) t;
  17. key1
  18. key2
  19. key3
  20. select name,col1,col2  from testarray2 lateral view explode(map('key1',1,'key2',2,'key3',3)) t1 as col1,col2;
  21. 小虎        key1        1
  22. 小虎        key2        2
  23. 小虎        key3        3
  24. 火火        key1        1
  25. 火火        key2        2
  26. 火火        key3        3
  27. select name,pos,col1  from testarray2 lateral view posexplode(weight) t1 as pos,col1;
  28. 小虎        0        150
  29. 小虎        1        170
  30. 小虎        2        180
  31. 火火        0        150
  32. 火火        1        180
  33. 火火        2        190
复制代码
5、Hive 列转行

  1. // testLieToLine
  2. name col1
  3. 小虎        150
  4. 小虎        170
  5. 小虎        180
  6. 火火        150
  7. 火火        180
  8. 火火        190
  9. create table testLieToLine(
  10.     name string,
  11.     col1 int
  12. )row format delimited
  13. fields terminated by '\t';
  14. select name,collect_list(col1) from testLieToLine group by name;
  15. // 结果
  16. 小虎        ["150","180","190"]
  17. 火火        ["150","170","180"]
  18. select  t1.name
  19.         ,collect_list(t1.col1)
  20. from (
  21.     select  name
  22.             ,col1
  23.     from testarray2
  24.     lateral view explode(weight) t1 as col1
  25. ) t1 group by t1.name;
复制代码
6、Hive自定义函数UserDefineFunction

6.1、UDF:一进一出

   定义UDF函数要注意下面几点:
    
  1.         <dependency>
  2.             <groupId>org.apache.hive</groupId>
  3.             <artifactId>hive-exec</artifactId>
  4.             <version>1.2.1</version>
  5.         </dependency>
复制代码
  打包的时间可能会出现错误
  Could not transfer artifact org.pentaho:pentaho-aggdesigner-algorithm:pom:5.1.5-jhyde

    办理方案:
在pom文件中修改hive-exec的配置
  1.         <dependency>
  2.             <groupId>org.apache.hive</groupId>
  3.             <artifactId>hive-exec</artifactId>
  4.             <exclusions>
  5.                 <!--排除pentaho-aggdesigner-algorithm依赖,不将它引入-->
  6.                 <exclusion>
  7.                     <groupId>org.pentaho</groupId>
  8.                     <artifactId>pentaho-aggdesigner-algorithm</artifactId>
  9.                 </exclusion>
  10.             </exclusions>
  11.         </dependency>
复制代码

  1. [/code]
  2. [list]
  3. [*]打成jar包并上传至Linux虚拟机
  4. [*]在hive shell中,使用 add jar 路径将jar包作为资源添加到hive环境中
  5. [/list] [code]add jar /usr/local/soft/bigdata19/hive-bigdata19-1.0-SNAPSHOT.jar;
复制代码

  1. create temporary function fxxx1 as 'MyUDF';
复制代码

  1. select fxx1(name) as fxx_name from students limit 10;
  2. #施笑槐$
  3. #吕金鹏$
  4. #单乐蕊$
  5. #葛德曜$
  6. #宣谷芹$
  7. #边昂雄$
  8. #尚孤风$
  9. #符半双$
  10. #沈德昌$
  11. #羿彦昌$
复制代码
案例2:转大写
  1. [/code] [size=1]函数加载方式[/size]
  2.    命令加载
  3.   这种加载只对本session有效
  4.   [code]# 1、将项目打包上传服务器:将打好的jar包传到linux系统中。(不要打依赖)
  5. # 进入到hive客户端,执行下面命令
  6. hive> add jar /usr/local/soft/bigdata17/data/xiaohu/hadoop-mapreduce-1.0-SNAPSHOT.jar
  7. # 2、创建一个临时函数名,要跟上面hive在同一个session里面:
  8. hive> create temporary function toUP as 'com.shujia.testHiveFun.udf.FirstUDF';
  9. 3、检查函数是否创建成功
  10. show functions;
  11. 4. 测试功能
  12. select toUp('abcdef');
  13. 5. 删除函数
  14. drop temporary function if exists toUp;
复制代码
  创建永久函数
  将jar上传HDFS:
  1. hadoop fs -put hadoop-mapreduce-1.0-SNAPSHOT.jar /jar/
复制代码
  在hive命令行中创建永久函数:
  1. create function myUp as 'com.shujia.testHiveFun.udf.FirstUDF' using jar 'hdfs:/jar/hadoop-mapreduce-1.0-SNAPSHOT.jar';
  2. create function bfy_fun as 'com.shujia.udfdemo.HiveTest' using jar 'hdfs:/shujia/bigdata19/jar/hive-udf.jar';
复制代码
  退出hive,再进入,实行测试:
  

删除永久函数,并检查:

6.2、UDTF:一进多出

   UDTF是一对多的输入输出,实现UDTF需要完成下面步骤
  M1001#xiaohu#S324231212,lkd#M1002#S2543412432,S21312312412#M1003#bfy
  1001 xiaohu 324231212
  1002 lkd 2543412432
  1003 bfy 21312312412
  继承org.apache.hadoop.hive.ql.udf.generic.GenericUDTF,
重写initlizer()、process()、close()。
实行流程如下:
  UDTF首先会调用initialize方法,此方法返回UDTF的返回行的信息(返回个数,类型)。
  初始化完成后,会调用process方法,真正的处置惩罚过程在process函数中,在process中,每一次forward()调用产生一行;假如产生多列可以将多个列的值放在一个数组中,然后将该数组传入到forward()函数。
  末了close()方法调用,对需要清理的方法进行清理。
    “key1:value1,key2:value2,key3:value3”
  key1 value1
  key2 value2
  key3 value3
  方法一:使用 explode+split

  1. [/code] [size=1]方法二:自定UDTF[/size]
  2. [list]
  3. [*]代码
  4. [/list] [code]
复制代码

  1. create temporary function my_udtf as 'com.shujia.testHiveFun.udtf.HiveUDTF';
  2. select my_udtf("key1:value1,key2:value2,key3:value3");
复制代码
  字段:id,col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12 共13列
  数据:
  a,1,2,3,4,5,6,7,8,9,10,11,12
  b,11,12,13,14,15,16,17,18,19,20,21,22
  c,21,22,23,24,25,26,27,28,29,30,31,32
  转成3列:id,hours,value
  例如:
  a,1,2,3,4,5,6,7,8,9,10,11,12
  a,0时,1
  a,2时,2
  a,4时,3
  a,6时,4
  …
  1. create table udtfData(
  2.     id string
  3.     ,col1 string
  4.     ,col2 string
  5.     ,col3 string
  6.     ,col4 string
  7.     ,col5 string
  8.     ,col6 string
  9.     ,col7 string
  10.     ,col8 string
  11.     ,col9 string
  12.     ,col10 string
  13.     ,col11 string
  14.     ,col12 string
  15. )row format delimited fields terminated by ',';
复制代码
代码:
  1. [/code] 添加jar资源:
  2. [code]add jar /usr/local/soft/HiveUDF2-1.0.jar;
复制代码
注册udtf函数:
  1. create temporary function my_udtf as 'MyUDTF';
复制代码
SQL:
  1. select id,hours,value from udtfData lateral view my_udtf(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12) t as hours,value ;
复制代码
6.3、UDAF:多进一出

Hive Shell

第一种:

  1. hive -e "select * from test1.students limit 10"
复制代码
第二种:

  1. hive -f hql文件路径
复制代码
  将HQL写在一个文件里,再使用 -f 参数指定该文件
  连续登岸问题

   在电商、物流和银行可能常常会遇到如许的需求:统计用户连续交易的总额、连续登岸天数、连续登岸开始和竣事时间、间隔天数等
  数据:

   注意:每个用户天天可能会有多条记录
  1. id        datestr          amount
  2. 1,2019-02-08,6214.23
  3. 1,2019-02-08,6247.32
  4. 1,2019-02-09,85.63
  5. 1,2019-02-09,967.36
  6. 1,2019-02-10,85.69
  7. 1,2019-02-12,769.85
  8. 1,2019-02-13,943.86
  9. 1,2019-02-14,538.42
  10. 1,2019-02-15,369.76
  11. 1,2019-02-16,369.76
  12. 1,2019-02-18,795.15
  13. 1,2019-02-19,715.65
  14. 1,2019-02-21,537.71
  15. 2,2019-02-08,6214.23
  16. 2,2019-02-08,6247.32
  17. 2,2019-02-09,85.63
  18. 2,2019-02-09,967.36
  19. 2,2019-02-10,85.69
  20. 2,2019-02-12,769.85
  21. 2,2019-02-13,943.86
  22. 2,2019-02-14,943.18
  23. 2,2019-02-15,369.76
  24. 2,2019-02-18,795.15
  25. 2,2019-02-19,715.65
  26. 2,2019-02-21,537.71
  27. 3,2019-02-08,6214.23
  28. 3,2019-02-08,6247.32
  29. 3,2019-02-09,85.63
  30. 3,2019-02-09,967.36
  31. 3,2019-02-10,85.69
  32. 3,2019-02-12,769.85
  33. 3,2019-02-13,943.86
  34. 3,2019-02-14,276.81
  35. 3,2019-02-15,369.76
  36. 3,2019-02-16,369.76
  37. 3,2019-02-18,795.15
  38. 3,2019-02-19,715.65
  39. 3,2019-02-21,537.71
复制代码
建表语句

  1. create table deal_tb(
  2.     id string
  3.     ,datestr string
  4.     ,amount string
  5. )row format delimited fields terminated by ',';
复制代码
计算逻辑


  1. [/code]
  2. [list]
  3. [*] 根据用户ID分组按日期排序,将日期和分组序号相减得到连续登岸的开始日期,假如开始日期相同说明连续登岸
  4. [*] [i]datediff(string end_date,string start_date);[/i] 即是0说明连续登录
  5. [*] 统计用户连续交易的总额、连续登岸天数、连续登岸开始和竣事时间、间隔天数
  6. [/list] [code]
复制代码

  1. 1        2019-02-07        13600.23        3        2019-02-08        2019-02-10 NULL
  2. 1        2019-02-08        2991.650        5        2019-02-12        2019-02-16        1
  3. 1        2019-02-09        1510.8                2        2019-02-18        2019-02-19        1
  4. 1        2019-02-10        537.71                1        2019-02-21        2019-02-21        1
  5. 2        2019-02-07        13600.23        3        2019-02-08        2019-02-10 NULL
  6. 2        2019-02-08        3026.649        4        2019-02-12        2019-02-15        1
  7. 2        2019-02-10        1510.8                2        2019-02-18        2019-02-19        2
  8. 2        2019-02-11        537.71                1        2019-02-21        2019-02-21        1
  9. 3        2019-02-07        13600.23        3        2019-02-08        2019-02-10 NULL
  10. 3        2019-02-08        2730.04                5        2019-02-12        2019-02-16        1
  11. 3        2019-02-09        1510.8                2        2019-02-18        2019-02-19        1
  12. 3        2019-02-10        537.71                1        2019-02-21        2019-02-21        1
复制代码
inated by ‘,’;
  1. 代码:```java```添加jar资源:```add jar /usr/local/soft/HiveUDF2-1.0.jar;
  2. ```注册udtf函数:```create temporary function my_udtf as 'MyUDTF';
  3. ```SQL:```select id,hours,value from udtfData lateral view my_udtf(col1,col2,col3,col4,col5,col6,col7,col8,col9,col10,col11,col12) t as hours,value ;
  4. ```## 6.3、UDAF:多进一出#### Hive Shell##### 第一种:```hive -e "select * from test1.students limit 10"
  5. ```##### 第二种:```hive -f hql文件路径
  6. ```> 将HQL写在一个文件里,再使用 -f 参数指定该文件#### 连续登岸问题> 在电商、物流和银行可能常常会遇到如许的需求:统计用户连续交易的总额、连续登岸天数、连续登岸开始和竣事时间、间隔天数等##### 数据:> 注意:每个用户天天可能会有多条记录```id        datestr          amount
  7. 1,2019-02-08,6214.23
  8. 1,2019-02-08,6247.32
  9. 1,2019-02-09,85.63
  10. 1,2019-02-09,967.36
  11. 1,2019-02-10,85.69
  12. 1,2019-02-12,769.85
  13. 1,2019-02-13,943.86
  14. 1,2019-02-14,538.42
  15. 1,2019-02-15,369.76
  16. 1,2019-02-16,369.76
  17. 1,2019-02-18,795.15
  18. 1,2019-02-19,715.65
  19. 1,2019-02-21,537.71
  20. 2,2019-02-08,6214.23
  21. 2,2019-02-08,6247.32
  22. 2,2019-02-09,85.63
  23. 2,2019-02-09,967.36
  24. 2,2019-02-10,85.69
  25. 2,2019-02-12,769.85
  26. 2,2019-02-13,943.86
  27. 2,2019-02-14,943.18
  28. 2,2019-02-15,369.76
  29. 2,2019-02-18,795.15
  30. 2,2019-02-19,715.65
  31. 2,2019-02-21,537.71
  32. 3,2019-02-08,6214.23
  33. 3,2019-02-08,6247.32
  34. 3,2019-02-09,85.63
  35. 3,2019-02-09,967.36
  36. 3,2019-02-10,85.69
  37. 3,2019-02-12,769.85
  38. 3,2019-02-13,943.86
  39. 3,2019-02-14,276.81
  40. 3,2019-02-15,369.76
  41. 3,2019-02-16,369.76
  42. 3,2019-02-18,795.15
  43. 3,2019-02-19,715.65
  44. 3,2019-02-21,537.71
  45. ```##### 建表语句```sqlcreate table deal_tb(
  46.     id string
  47.     ,datestr string
  48.     ,amount string
  49. )row format delimited fields terminated by ',';
  50. ```##### 计算逻辑* 先按用户和日期分组求和,使每个用户天天只有一条数据```sql```* 根据用户ID分组按日期排序,将日期和分组序号相减得到连续登岸的开始日期,假如开始日期相同说明连续登岸* *datediff(string end_date,string start_date);* 即是0说明连续登录* 统计用户连续交易的总额、连续登岸天数、连续登岸开始和竣事时间、间隔天数``````* 结果```1        2019-02-07        13600.23        3        2019-02-08        2019-02-10 NULL
  51. 1        2019-02-08        2991.650        5        2019-02-12        2019-02-16        1
  52. 1        2019-02-09        1510.8                2        2019-02-18        2019-02-19        1
  53. 1        2019-02-10        537.71                1        2019-02-21        2019-02-21        1
  54. 2        2019-02-07        13600.23        3        2019-02-08        2019-02-10 NULL
  55. 2        2019-02-08        3026.649        4        2019-02-12        2019-02-15        1
  56. 2        2019-02-10        1510.8                2        2019-02-18        2019-02-19        2
  57. 2        2019-02-11        537.71                1        2019-02-21        2019-02-21        1
  58. 3        2019-02-07        13600.23        3        2019-02-08        2019-02-10 NULL
  59. 3        2019-02-08        2730.04                5        2019-02-12        2019-02-16        1
  60. 3        2019-02-09        1510.8                2        2019-02-18        2019-02-19        1
  61. 3        2019-02-10        537.71                1        2019-02-21        2019-02-21        1
  62. ```
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4