数据仓库 Hive

Hive 3.1.2

目录

  • Hive 3.1.2
    • 1、数据仓库概念
      • 1.2、传统仓库面临的挑战
    • 2、Hive简介
      • 2.1、Hive的特点
      • 2.2、Hive的优缺点
      • 2.3、Hive与Hadoop生态系统中的关系
      • 2.4、Hive与传统数据库的对比分析
      • 2.5、Hive架构
        • 2.5.1. Client
        • 5.2.1. Metastore
        • 5.2.3. Driver
        • 5.2.4. 数据处理
      • 2.6、Hive元数据
    • 3、Hive的安装
      • 3.1、下载上传解压
      • 3.2、修改配置文件
      • 3.3、配置日志组件
      • 3.4、添加驱动包
      • 3.5、配置环境变量
      • 3.6、拷贝到其他节点
      • 3.7、客户端配置文件
      • 3.8、启动集群
      • 3.9、关机快照
      • 3.10、Hive的三种交互方式
    • 4、Hive的基本操作
      • 4.1、hive库操作
        • 4.1.1、创建数据库
        • 4.1.2、创建数据库和位置
        • 4.1.3、修改数据库
        • 4.1.4、数据库详细信息
        • 4.1.5、删除数据库
      • 4.2、Hive数据类型
        • 4.2.1、基础数据类型
        • 4.2.2、复杂数据类型
      • 4.3、Hive表操作
        • 4.3.1、创建表
        • 4.3.2、显示表
        • 4.3.3、重命名
        • 4.3.4、修改列
        • 4.3.5、删除表
      • 4.4、Hive内外部表
        • 4.4.1、hive内部表
        • 4.4.2、Hive外部表
      • 4.5、Hive载入数据
      • 4.6、Hive导出数据
      • 4.7、分区表
        • 4.7.1、静态分区(SP)
        • 4.7.2、动态分区(DP)
      • 4.8、分桶表
        • 4.8.1、业务场景
        • 4.8.2、数据分桶原理
        • 4.8.3、数据分桶优势
        • 4.8.4、数据分桶实战
        • 4.8.5、数据抽样算法
    • 5、Hive查询语法
      • 5.1、排序
        • 5.1.1、全局排序
        • 5.1.2、局部排序
        • 5.1.3、分区排序
        • 5.1.4、分区并排序
      • 5.2、Hive内置函数
        • 5.2.1、内置函数的分类
        • 5.2.2、独树一帜的UDTF
      • 5.3、Hive窗口函数
        • 5.3.1、聚合开窗函数
        • 5.3.2、排序开窗函数
      • 5.4、自定义函数

Hive是基于 Hadoop 的一个【数据仓库工具】,可以将结构化和半结构化的数据文件映射为一张数据库 表,并提供简单的 sql 查询功能

1、数据仓库概念

​ 数据仓库的一个比较公认的定义是一个面向主题的(Subject Oriented)集成的(Integrated)相对稳定的(Non-Volatile)、反映历史变化的(Time Variant)的数据集合,用于支持管理决策。

数据仓库的体系结构通常包含4个层次:数据源、数据存储和管理、数据服务、数据应用

1) **数据源:数据仓库的数据来源,**包含外部数据、现有业务的(OLTP,联机事务处理)系统和文档资料等。

2)数据存储和管理:主要涉及对数据的存储和管理,包括数据仓库、数据集市、数据仓库监视、运行与维护的元数据管理等。

3)数据服务:为前端工具和应用 提供数据服务。可以直接从数据仓库中获取数据 提供前端应用使用。

4)数据应用:直接面向最终用户,包括数据查询工具、数据分析工具、数据挖掘工具等。

  • ETL(Extract - Transform - Load ):数据抽取(Extracting)、清洗(Cleaning)、转换(Transformation)、加载(Load)工具,简称为ETL工具,完成数据的集成。
    • 数据抽取:就是从数据源中选择数据仓库需要的数据。数据抽取的技术难点在于要针对不同平台、不同结构、不同厂商的数据库,设计不同的抽取工具。
    • 数据清洗:为了保证数据的质量,对抽取得到的数据要进行清洗,例如,消除不一致性(同名异义、异名同义等)、统一计量单位、估算默认值,等等。
    • 数据转换:是将清洗后的数据按照数据仓库的主题进行组织。
    • 数据加载,就是将数据装入数据仓库中。

1.2、传统仓库面临的挑战

  • (1)无法满足快速增长的海量数据存储需求。
  • (2)无法有效处理不同数据类型的数据。
  • (3)计算和处理能力不足。

2、Hive简介

  • Hive是一个构建在Hadoop之上的数据仓库工具
  • 其本身并不存储和处理数据,而是依赖HDFS来存储数据,依赖MapReduce(或者Tez、Spark)来处理数据
  • Hive定义 了简单的类似SQL的查询语言–HiveQL,它与大部分SQL语法兼容。
  • 用户可以通过编写的HiveQL语句运行MapReduce任务。
  • 是一个可以提供有效、合理、直观组织和使用数据的模型。

2.1、Hive的特点

  • 可扩展性

    ​   Hive可以自由的扩展集群的规模,一般情况下不需要重启服务 。

  • 延伸性

    ​    Hive支持自定义函数,用户可以根据自己的需要来实现自己的函数 。

  • 采用批处理方式处理海量数据

    ​    Hive需要把HiveQL语句转换成MapReduce任务进行运行; 数据仓库存储的是静态数据,对静态数据的分析适合采用批处理方式,不需要 快速响应给出结果,而且数据本身也不会频繁变化。

  • 容错

    ​   即使节点出现错误,SQL仍然可以完成执行。

  • 提供适合数据仓库操作的工具

    ​    Hive本身提供了一系列对数据进行提取转化加载的工具,可以存储、查询和分 析存储在Hadoop中的大规模数据;

2.2、Hive的优缺点

  1. 优点
  • 1 ) 操作接口采用类SQL语法,提供快速开发的能力(简单、容易上手)
  • 2 ) 避免了去写MapReduce,减少开发人员的学习成本
  • 3 ) Hive的执行延迟比较高,因此Hive常用于数据分析,对实时性要求不高的场合。
  • 4 ) Hive优势在于处理大数据,对于处理小数据没有优势,因为Hive的执行延迟比较高。
  • 5 ) Hive支持用户自定义函数,用户可以根据自己的需求来实现自己的函数。
  • 6 ) 集群可自由拓展并且具有良好的容错性,节点出现问题SQL仍可完成执行。
  1. 缺点
  • 1 ) Hive的HQL表达能力有限
    • (1)迭代式算法无法表达
    • (2)数据挖掘方面不擅长
  • 2 ) Hive的效率比较低
    • (1)Hive自动生成的MapReduce作业,通常情况下不够智能化
    • (2)Hive调优比较困难,粒度较粗

2.3、Hive与Hadoop生态系统中的关系

数据仓库 Hive_第1张图片

  • Hive依赖于HDFS 存储数据

     HDFS作为高可靠性的底层存储,用来存储海量数据

  • Hive依赖于MapReduce 处理数据

      MapReduce对这些海量数据进行处理,实现高性能计算,用HiveQL语句 编写的处理逻辑最终均要转化为MapReduce任务来运行

  • Pig可以作为Hive的替代工具

    ​    pig是一种数据流语言和运行环境,适合用于Hadoop和MapReduce平台 上查询半结构化数据集。常用于ETL过程的一部分,即将外部数据装载到 Hadoop集群中,然后转换为用户期待的数据格式

  • HBase 提供数据的实时访问

    ​    HBase一个面向列的、分布式的、可伸缩的数据库,它可以提供数据的实 时访问功能,而Hive只能处理静态数据,主要是BI报表数据,所以HBase 与Hive的功能是互补的,它实现了Hive不能提供功能。

2.4、Hive与传统数据库的对比分析

数据仓库 Hive_第2张图片

Hive与传统数据库的区别主要体现在以下几个方面:

  • (1)数据插入:在传统数据库中同时支持导入单条数据和批量数据 ,而Hive中仅支持批量导入数据,因为Hive主要用来支持大规模数据 集上的数据仓库应用程序的运行,常见操作是全表扫描,所以单条插 入功能对Hive并不实用
  • (2)数据更新:更新是传统数据库中很重要的特性,Hive不支持数 据更新。Hive是一个数据仓库工具,而数据仓库中存放的是静态数据 ,所以Hive不支持对数据进行更新。
  • (3)索引:索引也是传统数据库中很重要的特性,Hive在hive 0.7版 本后已经可以支持索引了。但Hive不像传统的关系型数据库那样有键 的概念,它只提供有限的索引功能,使用户可以在某些列上创建索引 来加速一些查询操作,Hive中给一个表创建的索引数据被保存在另外 的表中。
  • (4)分区:传统的数据库提供分区功能来改善大型表以及具有各种 访问模式的表的可伸缩性,可管理性和提高数据库效率。Hive也支持 分区功能,Hive表组织成分区的形式,根据分区列的值对表进行粗略 的划分,使用分区可以加快数据的查询速度。
  • (5)执行延迟:因为Hive构建于HDFS与MapReduce上,所以对比 传统数据库来说Hive的延迟比较高,传统的SQL语句的延迟少于一秒 ,而HiveQL语句的延迟会达到分钟级。
  • (6)扩展性:传统关系数据库很难横向扩展,纵向扩展的空间也很 有限。相反Hive的开发环境是基于集群的,所以具有较好的可扩展性 。

2.5、Hive架构

​ Hive主要由以下3个模块组成:用户接口模块驱动模块以及元数据存储模块

数据仓库 Hive_第3张图片

2.5.1. Client

Hive允许client连接的方式有三个CLI(hive shell)、JDBC/ODBC(java访问hive)、WEBUI(浏览器访问 hive)。JDBC访问时中间件Thrift软件框架,跨语言服务开发。DDL DQL DML,整体仿写一套SQL语句。

  • client–需要下载安装包
  • JDBC/ODBC 也可以连接到Hive
    • 现在主流都在倡导第二种 HiveServer2/beeline
    • 做基于用户名和密码安全的一个校验
  • Web Gui
    • hive给我们提供了一套简单的web页面
    • 我们可以通过这套web页面访问hive 做的太简陋了
5.2.1. Metastore

元数据包括表名、表所属的数据库(默认是default)、表的拥有者、列/分区字段、表的类型(是否是 外部表)、表的数据所在目录等。

  • 一般需要借助于其他的数据载体(数据库)
  • 主要用于存放数据库的建表语句等信息
  • 推荐使用Mysql数据库存放数据
  • 连接数据库需要提供:uri username password driver
5.2.3. Driver

元数据存储在数据库中,默认存在自带的derby数据库(单用户局限性)中,推荐使用Mysql进行存储。

  • (1) 解析器(SQL Parser):将SQL字符串转换成抽象语法树AST,这一步一般都用第三方工具库完 成,比如ANTLR;对AST进行语法分析,比如表是否存在、字段是否存在、SQL语义是否有误。
  • (2) 编译器(Physical Plan):将AST编译生成逻辑执行计划。
  • (3) 优化器(Query Optimizer):对逻辑执行计划进行优化。
  • (4) 执行器(Execution):把逻辑执行计划转换成可以运行的物理计划。对于Hive来说,就是 MR/Spark。
5.2.4. 数据处理

​ Hive的数据存储在HDFS中,计算由MapReduce完成。HDFS和MapReduce是源码级别上的整合,两者 结合最佳。解释器、编译器、优化器完成HQL查询语句从词法分析、语法分析、编译、优化以及查询计 划的生成。

2.6、Hive元数据

Hive元数据库中一些重要的表结构及用途,方便Impala、SparkSQL、Hive等组件访问元数据库的理解。

  • 1、存储Hive版本的元数据表(VERSION),该表比较简单,但很重要。

  • 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:该表存储表对应的字段信息。

3、Hive的安装

节点\功能 metastore hiveserver2 client
node01 * *
node02 *
node03 *

PS: 安装前 请确认当前集群已经安装了Mysql数据库、ZooKeeper和Hadoop的Ha+Yarn
如果未安装:
链接: MySQL安装 :. https://blog.csdn.net/weixin_43660536/article/details/118033294
链接: ZooKeeper安装:. https://blog.csdn.net/weixin_43660536/article/details/118369963
链接: hadoop ha安装:. https://blog.csdn.net/weixin_43660536/article/details/118358298
链接: yarn搭建: . https://blog.csdn.net/weixin_43660536/article/details/118540991

3.1、下载上传解压

  • 下载地址

    • http://archive.apache.org/dist/hive/

    • [root@node01 ~]# tar -zxvf apache-hive-3.1.2-bin.tar.gz 
      [root@node01 ~]# mv apache-hive-3.1.2-bin /opt/yjx/
      [root@node01 ~]# cd /opt/yjx/apache-hive-3.1.2-bin/conf
      
  • 准备驱动包

    • hive-jdbc-2.1.1-cdh6.2.0-standalone.jar
    • mysql-connector-java-5.1.32-bin.jar

3.2、修改配置文件

  • 配置hive-env.sh

    • [root@node01 conf]# cp hive-env.sh.template hive-env.sh
      
    • [root@node01 conf]# vim hive-env.sh
      
    • export HADOOP_HOME=/opt/yjx/hadoop-3.1.2/
      export HIVE_CONF_DIR=/opt/yjx/apache-hive-3.1.2-bin/conf 
      export HIVE_AUX_JARS_PATH=/opt/yjx/apache-hive-3.1.2-bin/lib
      
  • 创建hive-site.xml

    • [root@node01 conf]# cp hive-default.xml.template hive-site.xml
      
    • [root@node01 conf]# vim hive-site.xml
      
    • 删除多余的配置文件 6897dd

    • 
      <property>
          <name>javax.jdo.option.ConnectionURLname>
          <value>jdbc:mysql://node01:3306/hive?createDatabaseIfNotExist=truevalue>
      property>
      <property>
          <name>javax.jdo.option.ConnectionDriverNamename>
          <value>com.mysql.jdbc.Drivervalue>
      property>
      <property>
          <name>javax.jdo.option.ConnectionUserNamename>
          <value>rootvalue>
      property>
      <property>
          <name>javax.jdo.option.ConnectionPasswordname>
          <value>123456value>
      property>
      <property>
          <name>datanucleus.schema.autoCreateAllname>
          <value>truevalue>
      property>
      <property>
          <name>hive.metastore.schema.verificationname>
          <value>falsevalue>
      property>
      
      <property>
          <name>hive.cli.print.headername>
          <value>truevalue>
      property>
      <property>
          <name>hive.cli.print.current.dbname>
          <value>truevalue>
      property>
      
      
      <property>
          <name>hive.server2.webui.hostname>
          <value>node01value>
      property>
      <property>
          <name>hive.server2.webui.portname>
          <value>10002value>
      property>
      
      
      <property>
          <name>hive.metastore.warehouse.dirname>
          <value>/hive/warehousevalue>
      property>
      
      
  • 修改core-site.xml

    • [root@node01 conf]# vim /opt/yjx/hadoop-3.1.2/etc/hadoop/core-site.xml
      
    • 后面添加配置信息

    • 
      <property>
          <name>hadoop.proxyuser.root.hostsname>
          <value>*value>
      property>
      
      <property>
          <name>hadoop.proxyuser.root.groupsname>
          <value>*value>
      property>
      

3.3、配置日志组件

  • 创建文件目录
[root@node01  ~]# mkdir -p /opt/yjx/apache-hive-3.1.2-bin/logs
[root@node01 conf]# cp hive-log4j2.properties.template  hive-log4j2.properties
[root@node01 conf]# vim hive-log4j2.properties
  • 修改配置

  • property.hive.log.dir = /opt/yjx/apache-hive-3.1.2-bin/logs
    

3.4、添加驱动包

  • Mysql驱动添加到hive的lib目录下

  • [root@node01 ~]# cp ~/mysql-connector-java-5.1.32-bin.jar /opt/yjx/apache-hive-3.1.2-bin/lib/
    
  • Guava包

    • 首先要删除hadoop中的guava-*.jar包

    • [root@node01 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/guava-*.jar
      [root@node01 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/guava-*.jar
      
    • 将Hive的Guava拷贝给Hive

    • [root@node01 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/
      [root@node01 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/
      

3.5、配置环境变量

  • vim /etc/profile
    
    • export HIVE_HOME=/opt/yjx/apache-hive-3.1.2-bin
      export PATH=$HIVE_HOME/bin:$PATH
      

3.6、拷贝到其他节点

  • hive文件夹

    • [root@node02 ~]# scp -r root@node01:/opt/yjx/apache-hive-3.1.2-bin /opt/yjx/
      [root@node03 ~]# scp -r root@node01:/opt/yjx/apache-hive-3.1.2-bin /opt/yjx/
      
  • 环境变量

    • [root@node01 ~]# scp /etc/profile root@node02:/etc/profile
      [root@node01 ~]# scp /etc/profile root@node03:/etc/profile
      
    • 【node123】source /etc/profile
      
  • core-stie.xml

    • [root@node01 ~]# scp /opt/yjx/hadoop-3.1.2/etc/hadoop/core-site.xml root@node02:/opt/yjx/hadoop-3.1.2/etc/hadoop/
      [root@node01 ~]# scp /opt/yjx/hadoop-3.1.2/etc/hadoop/core-site.xml root@node03:/opt/yjx/hadoop-3.1.2/etc/hadoop/
      
  • jar包

    • [root@node02 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/guava-*.jar
      [root@node02 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/guava-*.jar
      [root@node03 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/guava-*.jar
      [root@node03 ~]# rm -rf /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/guava-*.jar
      
      
      [root@node02 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/
      [root@node02 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/
      [root@node03 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/common/lib/
      [root@node03 ~]# cp /opt/yjx/apache-hive-3.1.2-bin/lib/guava-*.jar /opt/yjx/hadoop-3.1.2/share/hadoop/hdfs/lib/
      

3.7、客户端配置文件

  • 选取node03为客户端节点

    • [node03] vim /opt/yjx/apache-hive-3.1.2-bin/conf/hive-site.xml
      
    • <property>
          <name>hive.metastore.warehouse.dirname>
          <value>/hive/warehousevalue>
      property>
      <property>
          <name>hive.cli.print.headername>
          <value>truevalue>
      property>
      <property>
          <name>hive.cli.print.current.dbname>
          <value>truevalue>
      property>
      <property>
          <name>hive.metastore.schema.verificationname>
          <value>falsevalue>
      property>
      <property>
          <name>datanucleus.schema.autoCreateAllname>
          <value>truevalue>
      property>
      
      
      <property>
          <name>hive.metastore.urisname>
          <value>thrift://node01:9083value>
      property>
      

3.8、启动集群

  • 启动Zookeeper

    • 123】zkServer.sh start
      
  • 启动Hdfs+Yarn

    • [root@node01 ~]# start-all.sh
      
  • 初始化数据库

    • [root@node01 ~]# schematool -dbType mysql -initSchema
      
    • 在这里插入图片描述

    • 在这里插入图片描述

  • 启动Hive

    • //前台运行
      [root@node01 ~]# hive --service metastore
      //后台运行
      [root@node01 ~]# nohup hive --service metastore > /dev/null 2>&1 &
      
  • 启动HiveServer2(可启动可不启动

    • //前台启动
      [root@node01 ~]# hiveserver2
      //后台启动
      [root@node01 ~]# nohup hiveserver2 > /dev/null 2>&1 &
      
    • 连接

    • [root@node03 ~]# beeline -u jdbc:hive2://node01:10000 -n root
      
    • 连接成功,测试

    • show databases;
      create databases hive;
      show databases;
      // 查看是否创建成功;
      

3.9、关机快照

  • 退出hive,Ctrl+C停止Hive进程 ;

  • //关闭hadoop与yarn
    [root@node01 ~]# stop-all.sh
    //关闭ZooKeeper
    [123]# zkServer.sh start
    //关机
    [123]# shutdown -h now
    
  • 拍摄快照

3.10、Hive的三种交互方式

1)第一种交互方式

  shell交互Hive,用命令hive启动一个hive的shell命令行,在命令行中输入sql或者命令来和Hive交互。

服务端启动metastore服务(后台启动):nohup hive --service metastore > /dev/null 2>&1 &
进入命令:hive
退出命令行:quit;

2)第二种交互方式

  Hive启动为一个服务器,对外提供服务,其他机器可以通过客户端通过协议连接到服务器,来完成访问操作,这是生产环境用法最多的

hadoop fs -chmod -R 777 /yjx

服务端启动hiveserver2服务:
nohup hive --service metastore > /dev/null 2>&1 &
nohup hiveserver2 > /dev/null 2>&1 &

需要稍等一下,启动服务需要时间:

进入命令:1)先执行: beeline ,在执行: ! connect jdbc:hive2://node01:10000 
        2)或者直接执行:  beeline -u jdbc:hive2://node01:10000 -n root
退出命令行:!exit

3)第三种交互方式

  • 使用 –e 参数来直接执行hql的语句
bin/hive -e "show databases;"
  • 使用 –f 参数通过指定文本文件来执行hql的语句
vim hive.sql
use myhive;
select * from test;

保存退出

hive -f hive.sql

特点:执行完sql后,回到linux命令行。

4、Hive的基本操作

4.1、hive库操作

4.1.1、创建数据库

1)创建一个数据库,数据库在HDFS上的默认存储路径是/hive/warehouse/*.db

create database shop;

2)避免要创建的数据库已经存在错误,增加if not exists判断。(标准写法)

create database if not exists shop;   
4.1.2、创建数据库和位置
create database if not exists school location '/school.db';
4.1.3、修改数据库

数据库的其他元数据信息都是不可更改的,包括数据库名和数据库所在的目录位置。

alter database school set dbproperties('createtime'='20201213');
4.1.4、数据库详细信息

1)显示数据库(show)

show databases;

2)可以通过like进行过滤

show databases like 's*';
  1. 查看详情(desc)
desc database school;

4)切换数据库(use)

use school;
4.1.5、删除数据库

1)最简写法

drop database school;

2)如果删除的数据库不存在,最好使用if exists判断数据库是否存在。否则会报错:FAILED: SemanticException [Error 10072]: Database does not exist: db_hive

drop database if exists school;

3)如果数据库不为空,使用cascade命令进行强制删除。报错信息如下FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask. InvalidOperationException(message:Database db_hive is not empty. One or more tables exist.)

drop database if exists school cascade;

4.2、Hive数据类型

4.2.1、基础数据类型
类型 Java数据类型 描述
TINYINT byte 8位有符号整型。取值范围:-128~127。
SMALLINT short 16位有符号整型。取值范围:-32768~32767。
INT int 32位有符号整型。取值范围:-2 31 ~2 31 -1。
BIGINT long 64位有符号整型。取值范围:-2 63 +1~2 63 -1。
BINARY 二进制数据类型,目前长度限制为8MB。
FLOAT float 32位二进制浮点型。
DOUBLE double 64位二进制浮点型。
DECIMAL(precision,scale) 10进制精确数字类型。precision:表示最多可以表示多少位的数字。取值范围:1 <= precision <= 38scale:表示小数部分的位数。取值范围: 0 <= scale <= 38。如果不指定以上两个参数,则默认为decimal(10,0)
VARCHAR(n) 变长字符类型,n为长度。取值范围:1~65535。
CHAR(n) 固定长度字符类型,n为长度。最大取值255。长度不足则会填充空格,但空格不参与比较。
STRING string 字符串类型,目前长度限制为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按照与当前时区相符的方式来展现。
BOOLEAN boolean BOOLEAN类型。取值:True、False。
4.2.2、复杂数据类型
类型 定义方法 构造方法
ARRAY array``array> array(1, 2, 3)``array(array(1, 2), array(3, 4))
MAP map``map> map(“k1”, “v1”, “k2”, “v2”)``map(1S, array(‘a’, ‘b’), 2S, array(‘x’, ‘y’))
STRUCT struct``struct, field3:map> 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表操作

4.3.1、创建表
CREATE [EXTERNAL] TABLE [IF NOT EXISTS] table_name 
[(col_name data_type [COMMENT col_comment], ...)] 
[COMMENT table_comment] 
[PARTITIONED BY (col_name data_type [COMMENT col_comment], ...)] 
[CLUSTERED BY (col_name, col_name, ...) 
[SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS] 
[ROW FORMAT row_format] 
[STORED AS file_format] 
[LOCATION hdfs_path]


字段解释说明:
- CREATE TABLE 
	创建一个指定名字的表。如果相同名字的表已经存在,则抛出异常;用户可以用 IF NOT EXISTS 选项来忽略这个异常。

- EXTERNAL
	关键字可以让用户创建一个外部表,在建表的同时指定一个指向实际数据的路径(LOCATION)
	创建内部表时,会将数据移动到数据仓库指向的路径(默认位置);
	创建外部表时,仅记录数据所在的路径,不对数据的位置做任何改变。在
	删除表的时候,内部表的元数据和数据会被一起删除,而外部表只删除元数据,不删除数据。

- COMMENT:
	为表和列添加注释。

- PARTITIONED BY
	创建分区表

- CLUSTERED BY
	创建分桶表

- SORTED BY
	不常用

- ROW FORMAT 
  DELIMITED [FIELDS TERMINATED BY char] [COLLECTION ITEMS TERMINATED BY char] [MAP KEYS TERMINATED BY char] [LINES TERMINATED BY char] | SERDE serde_name [WITH SERDEPROPERTIES (property_name=property_value, property_name=property_value, ...)]
	用户在建表的时候可以自定义SerDe或者使用自带的SerDe。
	如果没有指定ROW FORMAT 或者ROW FORMAT DELIMITED,将会使用自带的SerDe。
	在建表的时候,用户还需要为表指定列,用户在指定表的列的同时也会指定自定义的SerDe,Hive通过SerDe确定表的具体的列的数据。
	SerDe是Serialize/Deserilize的简称,目的是用于序列化和反序列化。

- STORED AS指定存储文件类型
	常用的存储文件类型:SEQUENCEFILE(二进制序列文件)、TEXTFILE(文本)、RCFILE(列式存储格式文件)
	如果文件数据是纯文本,可以使用STORED AS TEXTFILE。
	如果数据需要压缩,使用 STORED AS SEQUENCEFILE。

- LOCATION :
	指定表在HDFS上的存储位置。

- LIKE
	允许用户复制现有的表结构,但是不复制数据。
  • 根据数据创建表结构

  • 案例1:简单用户信息

    • 1,admin,123456,男,18
      2,zhangsan,abc123,男,23
      3,lisi,654321,女,16
      
    • create external table t_user(
      id int,
      uname string,
      pwd string,
      gender string,
      age int
      )
      row format delimited fields terminated by ','
      lines terminated by '\n';
      
      --载入数据代码
      load data inpath '/yjx/user.txt' into table t_user;
      
  • 案例2:复杂人员信息

    • songsong,bingbing_lili,xiao song:18_xiaoxiao song:19,hui long guan_beijing
      yangyang,caicai_susu,xiao yang:18_xiaoxiao yang:19,chao yang_beijing
      
    • create table IF NOT EXISTS t_person(
      name string,
      friends array<string>,
      children map<string,int>,
      address struct<street:string ,city:string>
      )
      row format delimited fields terminated by ','
      collection items terminated by '_'
      map keys terminated by ':'
      lines terminated by '\n';
      
      --载入数据代码
      load data inpath '/yjx/person.txt' into table t_person;
      
4.3.2、显示表
show tables;
show tables like 'u';
desc t_person;
desc formatted t_person;
4.3.3、重命名

内部表(同时修改文件目录)外部表(因为目录是共享的,所以不会修改目录名称)

  • 基本语法
alter table old_table_name rename to new_table_name;
  • 把t_old改成t_new
alter table t_old rename to t_new;
4.3.4、修改列
  • 查询表结构
desc test_new;
  • 添加列
alter table test_new add columns (education string);
  • 查询表结构
desc test_new;
  • 更新列
alter table test_new change education educationnew string;
4.3.5、删除表
drop table test_new;

4.4、Hive内外部表

4.4.1、hive内部表
  • 创建好表的时候,HDFS会在当前表所属的库中创建一个文件夹

  • 当设置表路径的时候,如果直接指向一个已有的路径,可以直接去使用文件夹中的数据

  • 当load数据的时候,就会将数据文件存放到表对应的文件夹中

  • 而且数据一旦被load,就不能被修改

  • 我们查询数据也是查询文件中的文件,这些数据最终都会存放到HDFS

  • 当我们删除表的时候,表对应的文件夹会被删除,同时数据也会被删除

4.4.2、Hive外部表
  • 外部表说明

    • 外部表因为是指定其他的hdfs路径的数据加载到表中来,所以hive会认为自己不完全独占这份数据
    • 删除hive表的时候,数据仍然保存在hdfs中,不会删除。
  • 操作案例:

  • 分别创建dept,emp,salgrade。并加载数据。

    • 创建数据文件存放的目录

    • hdfs dfs -mkdir -p /yjx/dept
      hdfs dfs -mkdir -p /yjx/emp
      hdfs dfs -mkdir -p /yjx/salgrade
      
    • 创建dept表

    • CREATE EXTERNAL TABLE IF NOT EXISTS dept (
        DEPTNO int,
        DNAME varchar(255),
        LOC varchar(255)
      ) row format delimited fields terminated by ','
      location '/yjx/dept';
      
      10,ACCOUNTING,NEW YORK
      20,RESEARCH,DALLAS
      30,SALES,CHICAGO
      40,OPERATIONS,BOSTON
      
    • 创建emp表

    • CREATE EXTERNAL TABLE IF NOT EXISTS emp (
         EMPNO int,
         ENAME varchar(255),
         JOB varchar(255),
         MGR int,
         HIREDATE date,
         SAL decimal(10,0),
         COMM decimal(10,0),
         DEPTNO int
       ) row format delimited fields terminated by ','
       location '/yjx/emp';
       
      7369,SMITH,CLERK,7902,1980-12-17,800,null,20
      7499,ALLEN,SALESMAN,7698,1981-02-20,1600,300,30
      7521,WARD,SALESMAN,7698,1981-02-22,1250,500,30
      7566,JONES,MANAGER,7839,1981-04-02,2975,null,20
      7654,MARTIN,SALESMAN,7698,1981-09-28,1250,1400,30
      7698,BLAKE,MANAGER,7839,1981-05-01,2850,null,30
      7782,CLARK,MANAGER,7839,1981-06-09,2450,null,10
      7788,SCOTT,ANALYST,7566,1987-07-13,3000,null,20
      7839,KING,PRESIDENT,null,1981-11-17,5000,null,10
      7844,TURNER,SALESMAN,7698,1981-09-08,1500,0,30
      7876,ADAMS,CLERK,7788,1987-07-13,1100,null,20
      7900,JAMES,CLERK,7698,1981-12-03,950,null,30
      7902,FORD,ANALYST,7566,1981-12-03,3000,null,20
      7934,MILLER,CLERK,7782,1982-01-23,1300,null,10
      
    • 创建salgrade表

    • CREATE EXTERNAL TABLE IF NOT EXISTS salgrade (
        GRADE int,
        LOSAL int,
        HISAL int
      ) row format delimited fields terminated by ','
      location '/yjx/salgrade';
      
      1,700,1200
      2,1201,1400
      3,1401,2000
      4,2001,3000
      5,3001,9999
      

4.5、Hive载入数据

  • 基本语法

    • load data [local] inpath 'datapath' [overwrite] into table student [partition (partcol1=val1,)];
      
      --load data 
      	加载数据
      --[local] 
      	本地,不加Local就是从HDFS,如果是HDFS,将会删除掉原来的数据
      --inpath 
      	数据的路径
      --'datapath' 
      	具体的路径,要参考本地还是HDFS
      --[overwrite] 
      	覆盖
      --into table 
      	加入到表
      --student 
      	表的名字
      --[partition (partcol1=val1,…)] 
      	分区
      
  • 加载linux本地数据

-- 切记必须和hiveserver2在同一个节点才可以上传否则
-- SemanticException Line 1:23 Invalid path ''/root/d3.txt'': No files matching path file
load data local inpath '/root/user.txt' into table t_user;
  • 加载HDFS数据
load data inpath '/yjx/user.txt' into table t_user;
  • 加载并覆盖已有数据
load data inpath '/yjx/user.txt' overwrite into table t_user;
  • 通过查询插入数据

    • 创建表

    • create table t_user1(
      id int,
      uname string 
      )
      row format delimited fields terminated by ','  
      lines terminated by '\n';
      
      create table t_user2(
      id int,
      pwd string 
      )
      row format delimited fields terminated by ','  
      lines terminated by '\n';
      
    • 插入查询结果

    • --将查询结果插入一张表
      insert overwrite table t_user1 select id,uname from t_user;
      insert overwrite table t_user2 select id,pwd from t_user;
      
      --将查询结果一次性存放到多张表
      from t_user 
      insert overwrite table t_user1 select id,uname
      insert overwrite table t_user2 select id,pwd;
      

4.6、Hive导出数据

  • 将表中的数据备份

    • 将查询结果存放到本地
    //创建存放数据的目录
    mkdir -p /root/yjx
    
    //导出查询结果的数据(导出到Node01上)
    insert overwrite local directory '/root/person_data' select * from t_person;
    
    • 按照指定的方式将数据输出到本地
    -- 创建存放数据的目录
    mkdir -p /root/yjx
    
    -- 导出查询结果的数据
    insert overwrite local directory '/root/yjx/person' 
    ROW FORMAT DELIMITED fields terminated by ',' 
    collection items terminated by '-' 
    map keys terminated by ':' 
    lines terminated by '\n' 
    select * from t_person;
    
    • 将查询结果输出到HDFS
    -- 创建存放数据的目录
    hdfs dfs -mkdir -p /yjx/copy
    
    -- 导出查询结果的数据
    insert overwrite directory '/yjx/copy/user' 
    ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' 
    select * from t_user;
    
  • 直接使用HDFS命令保存表对应的文件夹

    // 创建存放数据的目录
    hdfs dfs -mkdir -p /yjx/person
    
    // 使用HDFS命令拷贝文件到其他目录
    hdfs dfs -cp /hive/warehouse/t_person/*  /yjx/person
    
  • 将表结构和数据同时备份

    • 将数据导出到HDFS
    //创建存放数据的目录
    hdfs dfs -mkdir -p /yjx/copy
    
    //导出查询结果的数据
    export table t_person to '/yjx/copy';
    
    • 删除表结构
    drop table t_person;
    
    • 恢复表结构和数据
    import from '/yjx/copy';
    
    • 需要注意的是:时间不同步,会导致导入导出失败

4.7、分区表

  • 在大数据中,最常见的一种思想就是分治,我们可以把大的文件切割划分成一个个的小的文件,这样每次操作一个个小的文件就会很容易了,同样的道理,在hive当中也是支持这种思想的,就是我们可以把大的数据,按照每天或者每小时切分成一个个小的文件,这样去操作小的文件就会容易很多了。

  • 假如现在我们公司一天产生3亿的数据量,那么为了方便管理和查询,

    • 建立分区(可按日期 部门等具体业务分区)
    • 分门别类的管理。

数据仓库 Hive_第4张图片

4.7.1、静态分区(SP)
  • 静态分区(SP)static partition–partition by (字段 类型)
    • 借助于物理的文件夹分区,实现快速检索的目的。
    • 一般对于查询比较频繁的列设置为分区列。
    • 分区查询的时候直接把对应分区中所有数据
  • 创建单分区表语法
CREATE TABLE IF NOT EXISTS t_student (
sno int,
sname string
) partitioned by(grade int)
row format delimited fields terminated by ',';
--  分区的字段不要和表的字段相同。相同会报错error10035
1,zhangsanfeng01,1
2,zhangsanfeng02,1
3,zhangsanfeng03,1
4,zhangsanfeng04,1
5,zhangsanfeng05,1
6,zhangsanfeng06,1

19,zhangsanfeng19,4
20,zhangsanfeng20,4
21,zhangsanfeng21,4
-- 载入数据
-- 将相应年级一次导入
load data inpath '/yjx/student.txt' into table t_student partition(grade=1);
  • 创建多分区表语法
CREATE TABLE IF NOT EXISTS t_teacher (
tno int,
tname string
) partitioned by(grade int,clazz int)
row format delimited fields terminated by ',';

--注意:前后两个分区的关系为父子关系,也就是grade文件夹下面有多个clazz子文件夹。
1,jueyuan01,1,1
2,jueyuan02,1,1
3,jueyuan03,1,2
4,jueyuan04,1,2
5,jueyuan05,1,3
6,jueyuan06,1,3
7,jueyuan07,2,1
8,jueyuan08,2,1
9,jueyuan09,2,2

--载入数据
load data inpath '/yjx/teacher11.txt' into table t_teacher partition(grade=1,class=1);
  • 分区表查询
select * from t_student where grade = 1 ;
  • 查看分区
show partitions t_student;
  • 添加分区
alter table t_student add partition (day='99990102');

alter table t_student add partition (day='99990103') location '99990103';
  • 删除分区
alter table salgrade2 drop partition (day='99990102');
4.7.2、动态分区(DP)
  • 动态分区(DP)dynamic partition

  • 静态分区与动态分区的主要区别在于静态分区是手动指定,而动态分区是通过数据来进行判断。

  • 详细来说,静态分区的列是在编译时期通过用户传递来决定的;动态分区只有在SQL执行时才能决定

开启动态分区首先要在hive会话中设置如下的参数

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

其余的参数详细配置如下

设置为true表示开启动态分区的功能(默认为false--hive.exec.dynamic.partition=true;

设置为nonstrict,表示允许所有分区都是动态的(默认为strict)
-- hive.exec.dynamic.partition.mode=nonstrict; 

每个mapper或reducer可以创建的最大动态分区个数(默认为100) 
比如:源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认值100,则会报错
--hive.exec.max.dynamic.partition.pernode=100; 

一个动态分区创建可以创建的最大动态分区个数(默认值1000--hive.exec.max.dynamic.partitions=1000;

全局可以创建的最大文件个数(默认值100000--hive.exec.max.created.files=100000; 

当有空分区产生时,是否抛出异常(默认false-- hive.error.on.empty.partition=false;   
  • 案例1: 动态插入学生年级班级信息
--创建分区表
CREATE TABLE IF NOT EXISTS t_student_d (
sno int,
sname string
) partitioned by (grade int,clazz int)
row format delimited fields terminated by ',';

--创建外部表
CREATE EXTERNAL TABLE IF NOT EXISTS t_student_e (
sno int,
sname string,
grade int,
clazz int
) 
row format delimited fields terminated by ','
location "/yjx/student";

如果静态分区的话,我们插入数据必须指定分区的值。

如果想要插入多个班级的数据,我要写很多SQL并且执行24次很麻烦。

而且静态分区有可能会产生数据错误问题

-- 会报错 
insert overwrite table t_student partition (grade=1) select * from t_student_e where grade=1;

  如果使用动态分区,动态分区会根据select的结果自动判断数据应该load到哪儿分区去。

insert overwrite table t_student_d partition (grade,clazz) select * from t_student_e ;

4.8、分桶表

4.8.1、业务场景
  • 数据分桶的适用场景:
    • 分区提供了一个隔离数据和优化查询的便利方式,不过并非所有的数据都可形成合理的分区,尤其是需要确定合适大小的分区划分方式
    • 不合理的数据分区划分方式可能导致有的分区数据过多,而某些分区没有什么数据的尴尬情况
    • 分桶是将数据集分解为更容易管理的若干部分的另一种技术。
    • 分桶就是将数据按照字段进行划分,可以将数据按照字段划分到多个文件当中去。
4.8.2、数据分桶原理
  • Hive采用对列值哈希,然后除以桶的个数求余的方式决定该条记录存放在哪个桶当中。
    • bucket num = hash_function(bucketing_column) mod num_buckets
    • 列的值做哈希取余 决定数据应该存储到哪个桶

数据仓库 Hive_第5张图片

4.8.3、数据分桶优势
  • 方便抽样

    • 使取样(sampling)更高效。在处理大规模数据集时,在开发和修改查询的阶段,如果能在数据集的一小部分数据上试运行查询,会带来很多方便
  • 提高join查询效率

    • 获得更高的查询处理效率。桶为表加上了额外的结构,Hive 在处理有些查询时能利用这个结构。具体而言,连接两个在(包含连接列的)相同列上划分了桶的表,可以使用 Map 端连接 (Map-side join)高效的实现。比如JOIN操作。对于JOIN操作两个表有一个相同的列,如果对这两个表都进行了桶操作。那么将保存相同列值的桶进行JOIN操作就可以,可以大大较少JOIN的数据量。
4.8.4、数据分桶实战
  • -- 开启分桶功能
    set hive.enforce.bucketing=true;
    
    -- 设置Reduce个数
    -- 我们需要确保reduce 的数量与表中的bucket 数量一致
    -- bucket个数会决定在该表或者该表的分区对应的hdfs目录下生成对应个数的文件,而mapreduce的个数是根据文件块的个数据确定的map个数。
    set mapreduce.job.reduce=3;
    
  • -- 创建表
    CREATE TABLE t_citizen_bucket(
    idcard int,
    pname string,
    province int
    )clustered by(idcard) sorted by (pname desc) into 16 buckets
    row format delimited fields terminated by ','
    lines terminated by '\n';
    
    create EXTERNAL table t_citizen(
        idcard int,
        pname string,
        province int
    )row format delimited fields terminated by ',' 
    lines terminated by '\n'
    location '/yjx/citizen';
    
    
    -- 数据导入
    for (int i = 1000; i < 10000; i++) {
    	System.out.println(i + "," + "admin" + (new Random().nextInt(89999) + 10000) + "," + i % 34);
    }
    -- 将外部表的数据导入到分桶表 
    insert overwrite table t_citizen_bucket select * from t_citizen ;
    
    

在这里插入图片描述
数据仓库 Hive_第6张图片

4.8.5、数据抽样算法
  • 数据块抽样:
-- 该方式允许Hive随机抽取N行数据,数据总量的百分比(n百分比)或N字节的数据。
SELECT * FROM <Table_Name> TABLESAMPLE(N PERCENT|ByteLengthLiteral|N ROWS) s;

1) tablesample(n percent) 根据hive表数据的大小按比例抽取数据,并保存到新的hive表中。如:抽取原hive表中10%的数据
	注意:测试过程中发现,select语句不能带where条件且不支持子查询,可通过新建中间表或使用随机抽样解决
	create table xxx_new as select * from xxx tablesample(10 percent)
2)tablesample(n M) 指定抽样数据的大小,单位为M。
3)tablesample(n rows) 指定抽样数据的行数,其中n代表每个map任务均取n行数据

-- hive另外一种按照抽样百分比进行抽样的方式,该种方式基于行数,按照输入路径下的数据块的百分比进行抽样。
-- 这种抽样的最小单元是一个hdfs数据块,如果表的数据大小小于普通块大小128M,将返回所有行。
-- 基于百分比的抽样方式提供了一个变量,用于控制基于数据块的调优种子信息:

  • 桶表抽样:
-- tablesample是抽样语句,语法:TABLESAMPLE(BUCKET x OUT OF y)
-- 分桶语句中的分母表示的是数据将会被散列的桶的个数,分子表示将会选择的桶的个数。

-- x表示从哪个bucket开始抽取。
-- 例如,table总bucket数为32,tablesample(bucket 3 out of 16)
-- 表示总共抽取(32/16=)2个bucket的数据,分别为第3个bucket和第(3+16=)19个bucket的数据
-- y必须是table总bucket数的倍数或者因子。hive根据y的大小,决定抽样的比例。
-- 例如,table总共分了64份,当y=32时,抽取(64/32=)2个bucket的数据,当y=128时,抽取(64/128=)1/2个bucket的数据


select * from t_citizen_bucket tablesample(bucket 1 out of 16 on idcard); 
select * from t_citizen_bucket tablesample(bucket 2 out of 4 on idcard);
  • 随机抽样:
-- 使用RAND()函数和LIMIT关键字来获取样例数据,使用DISTRIBUTE和SORT关键字来保证数据是随机分散到mapper和reducer的。
-- ORDER BY RAND()语句可以获得同样的效果,但是性能没这么高。
SELECT * FROM <Table_Name> DISTRIBUTE BY RAND() SORT BY RAND() LIMIT <N rows to sample>;

select * from t_citizen_bucket DISTRIBUTE BY RAND() SORT BY RAND() LIMIT 10;

5、Hive查询语法

SELECT [ALL | DISTINCT] select_expr, select_expr, ...
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[ORDER BY col_list]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT [offset,] rows]

5.1、排序

5.1.1、全局排序
  • order by 会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时,需要较长的计算时间
  • 使用 order by子句排序 :ASC(ascend)升序(默认)| DESC(descend)降序
  • order by放在select语句的结尾
select * from 表名 order by 字段名1[,别名2...];
5.1.2、局部排序
  • sort by 不是全局排序,其在数据进入reducer前完成排序

  • 如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by 只保证每个reducer的输出有序,不保证全局有序

  • 设置reduce个数

    set mapreduce.job.reduce=3;
    set mapred.reduce.tasks=3;
    
  • 查看reduce个数

    set mapreduce.job.reduce;
    
  • 排序

    select * from 表名 sort by 字段名[,字段名...];
    
5.1.3、分区排序
  • distribute by(字段)根据指定的字段将数据分到不同的reducer,且分发算法是hash散列。

  • 类似MR中partition,进行分区,结合sort by使用。(注意:distribute by 要在sort by之前

  • 对于distrbute by 进行测试,一定要多分配reduce进行处理,否则无法看到distribute by的效果。

  • 设置reduce个数

set mapreduce.job.reduce=7;
  • 排序
select * from 表名 distribute by 字段名[,字段名...];

数据仓库 Hive_第7张图片

5.1.4、分区并排序
  • cluster by(字段)除了具有Distribute by的功能外,还会对该字段进行排序
  • cluster by = distribute by + sort by 只能默认升序,不能使用倒序
select * from 表名 sort cluster by 字段名[,字段名...];
select * from 表名 distribute by 字段名[,字段名...] sort by 字段名[,字段名...];

5.2、Hive内置函数

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
-- 1.查看系统自带函数
show functions;
-- 2.显示自带的函数的用法
desc function upper;
-- 3.详细显示自带的函数的用法
desc function extended upper;

数据仓库 Hive_第8张图片

5.2.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.2、独树一帜的UDTF
-- UDTF 进一出多
-- explode  可以将一组数组的数据变成一列表
select  explode(split(列名,"数据的分隔符")) from 表名;
-- lateral view 表生成函数,可以将explode的数据生成一个列表
select id,name,列名 from1,lateral view explode(split(1.列名,"数据的分隔符"))新列名 as 别列名;

-- UDTF 进多出一
-- collect_set()和collect_list()都是对多列转成一行,区别就是list里面可重复而set里面是去重的
-- concat_ws(':',collect_set(type))   ':' 表示你合并后用什么分隔,collect_set(stage)表示要合并表中的那一列数据
select 字段名,concat_ws(':',collect_set(列名)) as 别名 from 表名 group by id;
  • -- 创建数据库表
    create table t_movie1(
    id int,
    name string,
    types string
    )
    row format delimited fields terminated by ','
    lines terminated by '\n';
    
    -- 电影数据  movie1.txt
    -- 加载数据到数据库 load data inpath '/yjx/movie1.txt' into table t_movie1;
    1,这个杀手不太冷,剧情-动作-犯罪
    2,七武士,动作-冒险-剧情
    3,勇敢的心,动作-传记-剧情-历史-战争
    4,东邪西毒,剧情-动作-爱情-武侠-古装
    5,霍比特人,动作-奇幻-冒险
    
    -- explode  可以将一组数组的数据变成一列表
    select  explode(split(types,"-")) from t_movie1;
    
    -- lateral view 表生成函数,可以将explode的数据生成一个列表
    select id,name,type from t_movie1,lateral view explode(split(types,"-"))typetable as type;
    
  • -- 创建数据库表
    create table t_movie2(
    id int,
    name string,
    type string
    )
    row format delimited fields terminated by ','
    lines terminated by '\n';
    
    -- 电影数据 movie2.txt
    -- 加载数据到数据库 load data inpath '/yjx/movie2.txt' into table t_movie2;
    1,这个杀手不太冷,剧情
    1,这个杀手不太冷,动作
    1,这个杀手不太冷,犯罪
    2,七武士,动作
    2,七武士,冒险
    2,七武士,剧情
    3,勇敢的心,动作
    3,勇敢的心,传记
    3,勇敢的心,剧情
    3,勇敢的心,历史
    3,勇敢的心,战争
    4,东邪西毒,剧情
    4,东邪西毒,动作
    4,东邪西毒,爱情
    4,东邪西毒,武侠
    4,东邪西毒,古装
    5,霍比特人,动作
    5,霍比特人,奇幻
    5,霍比特人,冒险
    
    -- collect_set()和collect_list()都是对列转成行,区别就是list里面可重复而set里面是去重的
    -- concat_ws(':',collect_set(type))   ':' 表示你合并后用什么分隔,collect_set(stage)表示要合并表中的那一列数据
    select id,concat_ws(':',collect_set(type)) as types from t_movie2 group by id;
    
    

5.3、Hive窗口函数

  • 普通的聚合函数每组(Group by)只返回一个值,而开窗函数则可为窗口中的每行都返回一个值
  • 简单理解,就是对查询的结果多出一列,这一列可以是聚合值,也可以是排序值。
  • 开窗函数一般就是说的是over()函数,其窗口是由一个 OVER 子句 定义的多行记录
  • 开窗函数一般分为两类,聚合开窗函数和排序开窗函数
-- 聚合格式
select sum(字段名) over([partition by 字段名] [ order by 字段名]) as 别名,
	max(字段名) over() as 别名 
from 表名;
-- 排序窗口格式
select rank() over([partition by 字段名] [ order by 字段名]) as 别名 from 表名;
  • 测试数据

    • -- 创建表
      create table t_fraction(
      name string,
      subject string, 
      score int) 
      row format delimited fields terminated by ","
      lines terminated by '\n';
      
      -- 测试数据 fraction.txt
      孙悟空,语文,10
      孙悟空,数学,73
      孙悟空,英语,15
      猪八戒,语文,10
      猪八戒,数学,73
      猪八戒,英语,11
      沙悟净,语文,22
      沙悟净,数学,70
      沙悟净,英语,31
      唐玄奘,语文,21
      唐玄奘,数学,81
      唐玄奘,英语,23
      
      -- 上传数据
      load data inpath '/yjx/fraction.txt' into table t_fraction;
      
5.3.1、聚合开窗函数
  • sum(求和)min(最小)max(最大)avg(平均值)count(计数)

    • -- 
      select name,subject,score,sum(score) over() as sumover from t_fraction;
      +-------+----------+--------+----------+
      | name  | subject  | score  | sumover  |
      +-------+----------+--------+----------+
      | 唐玄奘   | 英语       | 23     | 321      |
      | 唐玄奘   | 数学       | 81     | 321      |
      | 唐玄奘   | 语文       | 21     | 321      |
      | 沙悟净   | 英语       | 31     | 321      |
      | 沙悟净   | 数学       | 12     | 321      |
      | 沙悟净   | 语文       | 22     | 321      |
      | 猪八戒   | 英语       | 11     | 321      |
      | 猪八戒   | 数学       | 73     | 321      |
      | 猪八戒   | 语文       | 10     | 321      |
      | 孙悟空   | 英语       | 15     | 321      |
      | 孙悟空   | 数学       | 12     | 321      |
      | 孙悟空   | 语文       | 10     | 321      |
      +-------+----------+--------+----------+
      
      select name,subject,score,
      sum(score) over() as sum1,
      sum(score) over(partition by subject) as sum2,
      sum(score) over(partition by subject order by score) as sum3, 
      -- 由起点到当前行的窗口聚合,和sum3一样
      sum(score) over(partition by subject order by score rows between unbounded preceding and current row) as sum4, 
      -- 当前行和前面一行的窗口聚合
      sum(score) over(partition by subject order by score rows between 1 preceding and current row) as sum5,
      -- 当前行的前面一行和后面一行的窗口聚合
      sum(score) over(partition by subject order by score rows between 1 preceding AND 1 following) as sum6,
      -- 当前和后面所有的行
      sum(score) over(partition by subject order by score rows between current row and unbounded following) as sum7
      from t_fraction;
      
      +-------+----------+--------+-------+-------+-------+-------+-------+-------+-------+
      | name  | subject  | score  | sum1  | sum2  | sum3  | sum4  | sum5  | sum6  | sum7  |
      +-------+----------+--------+-------+-------+-------+-------+-------+-------+-------+
      | 孙悟空   | 数学       | 12     | 359   | 185   | 12    | 12    | 12    | 31    | 185   |
      | 沙悟净   | 数学       | 19     | 359   | 185   | 31    | 31    | 31    | 104   | 173   |
      | 猪八戒   | 数学       | 73     | 359   | 185   | 104   | 104   | 92    | 173   | 154   |
      | 唐玄奘   | 数学       | 81     | 359   | 185   | 185   | 185   | 154   | 154   | 81    |
      | 猪八戒   | 英语       | 11     | 359   | 80    | 11    | 11    | 11    | 26    | 80    |
      | 孙悟空   | 英语       | 15     | 359   | 80    | 26    | 26    | 26    | 49    | 69    |
      | 唐玄奘   | 英语       | 23     | 359   | 80    | 49    | 49    | 38    | 69    | 54    |
      | 沙悟净   | 英语       | 31     | 359   | 80    | 80    | 80    | 54    | 54    | 31    |
      | 孙悟空   | 语文       | 10     | 359   | 94    | 10    | 10    | 10    | 31    | 94    |
      | 唐玄奘   | 语文       | 21     | 359   | 94    | 31    | 31    | 31    | 53    | 84    |
      | 沙悟净   | 语文       | 22     | 359   | 94    | 53    | 53    | 43    | 84    | 63    |
      | 猪八戒   | 语文       | 41     | 359   | 94    | 94    | 94    | 63    | 63    | 41    |
      +-------+----------+--------+-------+-------+-------+-------+-------+-------+-------+
      
      
    • 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 子句中指定的列的当前行中的值。
5.3.2、排序开窗函数
  • RANK() 排序相同时会重复,总数不会变

  • DENSE_RANK() 排序相同时会重复,总数会减少

  • ROW_NUMBER() 会根据顺序计算

    • select name,subject,score,
      rank() over(partition by subject order by score desc) rp,
      dense_rank() over(partition by subject order by score desc) drp,
      row_number() over(partition by subject order by score desc) rnp
      from t_fraction;
      
  • percent_rank() 计算给定行的百分比排名。可以用来计算超过了百分之多少的人

    • (当前行的rank值-1)/(分组内的总行数-1)

    • select name,subject,score,
      row_number() over(partition by subject order by score) as row_number,
      percent_rank() over(partition by subject order by score) as percent_rank
      from t_fraction;
      

5.4、自定义函数

  • 官网 https://cwiki.apache.org/confluence/display/Hive/HivePlugins

  • Hive自带了一些函数,比如:max/min等,但是数量有限,自己可以通过自定义的UDF来方便的扩展

  • 当Hive提供的内置函数无法满足你的业务处理需要的时候,此时可以考虑使用用户自定义函数

  • UDF(User-Defined-Function) 单行函数,一进一出

    • size/sqrt
  • UDAF(User- Defined Aggregation Funcation) 聚集函数,多进一出

    • count/max/min/sum/avg
  • UDTF(User-Defined Table-Generating Functions) 一进多出

    • lateral view explode()

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