欢迎光临
我们一直在努力

Hive大数据实战指南:从入门到精通

Apache Hive 完整知识总结与使用教程

版本参考:Apache Hive 4.x / 3.1.x(当前主流生产版本) 官方网站:https://hive.apache.org/ 官方文档:https://cwiki.apache.org/confluence/display/Hive/Home


目录

  • Hive 概述
  • Hive 核心架构
  • Hive 数据模型
  • 安装与环境配置
    • 4.1 前置条件
    • 4.2 二进制包安装(传统方式)
    • 4.3 配置 MySQL 作为 Metastore
    • 4.4 启动 Hive 服务
    • 4.5 Docker 快速启动(推荐入门)
  • HiveQL DDL 数据定义语言
    • 5.1 数据库操作
    • 5.2 表的创建(内部表 vs 外部表)
    • 5.3 分区表
    • 5.4 分桶表
    • 5.5 表结构修改
    • 5.6 视图(View)
  • HiveQL DML 数据操作语言
    • 6.1 数据加载(LOAD DATA)
    • 6.2 INSERT 语句
    • 6.3 SELECT 查询详解
    • 6.4 JOIN 操作
    • 6.5 子查询与 CTE
    • 6.6 窗口函数
    • 6.7 ACID 事务(UPDATE / DELETE)
  • Hive 数据类型详解
  • Hive 文件格式与存储
  • SerDe(序列化/反序列化)
  • Hive 内置函数大全
  • 用户自定义函数(UDF / UDAF / UDTF)
  • Hive 执行引擎
  • Hive 性能调优
  • Hive 分区管理深入
  • Hive 元数据服务(Metastore)
  • HiveServer2 与 Beeline
  • Hive 安全机制
  • Hive 与生态系统集成
  • Hive 4.x 新特性
  • 常见问题与排查
  • 最佳实践总结
  • Hive 与其他技术对比
  • 附录:配置项速查 & 官方资源

  • 1. Hive 概述

    1.1 什么是 Apache Hive?

    Apache Hive 是一个构建在 Apache Hadoop 之上的分布式数据仓库软件系统,由 Facebook 于 2007 年开发,后捐献给 Apache 软件基金会。

    Hive 的核心价值在于:它提供了类 SQL 的查询语言 HiveQL(HQL),使得熟悉 SQL 的开发者和分析师无需学习 MapReduce 编程即可处理和分析存储在 HDFS 中的海量数据。HiveQL 在底层被自动翻译为 MapReduce、Apache Tez 或 Apache Spark 作业执行。

    开发者写 HQL 查询 → Hive 编译优化 → 生成 MapReduce/Tez/Spark 作业 → 在 YARN 上执行 → 结果写回 HDFS

    1.2 Hive 解决了什么问题?

    传统 MapReduce 痛点Hive 的解法
    必须用 Java 编写 MapReduce 程序 HQL(类 SQL),门槛极低
    开发周期长,调试困难 声明式查询,框架自动生成执行计划
    无法方便地管理结构化数据的 Schema Metastore 统一管理表结构、分区等元数据
    缺乏数据发现和数据抽象机制 提供数据仓库级别的抽象:数据库、表、分区、视图
    批量数据分析没有统一入口 标准 JDBC/ODBC 接口,BI 工具可直接对接

    1.3 Hive 的核心特性

    • SQL 接口:支持 SQL:2003、SQL:2011、SQL:2016 大量标准功能,降低大数据学习门槛
    • 可扩展性:通过 UDF/UDAF/UDTF 支持自定义函数,通过 SerDe 扩展支持的数据格式
    • 多执行引擎:支持 MapReduce、Apache Tez、Apache Spark 作为底层执行引擎
    • 多存储格式:支持 TextFile、ORC、Parquet、Avro、RCFile 等多种文件格式
    • 元数据管理:HMS(Hive Metastore Service)提供集中式元数据存储和管理
    • 分区与分桶:通过分区(Partition)和分桶(Bucketing)优化查询性能
    • ACID 支持:Hive 0.14+ 支持行级 INSERT/UPDATE/DELETE(需 ORC 格式 + 事务配置)
    • Sub-second 查询:通过 LLAP(Live Long and Process)实现交互式亚秒级查询
    • 多云兼容:支持 HDFS、Amazon S3、Azure ADLS、Google Cloud Storage 等存储后端

    1.4 Hive 发展历程

    版本里程碑时间重要变化
    Hive 0.x(初始版本) 2008~2012 Facebook 开源,基本 DDL/DML,仅支持 MapReduce
    Hive 0.13 2014 原生支持 Parquet 格式
    Hive 0.14 2014 ACID 事务支持(UPDATE/DELETE),ORC 格式
    Hive 2.0 2016 LLAP(交互式查询),HiveServer2 改进,Hive CLI 弃用
    Hive 3.0 2018 移除索引,ACID 默认开启,Druid 集成,去除旧 API
    Hive 3.1.x 2019~2022 主流生产版本,稳定性大幅提升
    Hive 4.0 2024 JDK 21 支持、Iceberg v3 深度集成、REST Catalog、删除向量
    Hive 4.2.0 2025 当前最新版,增强 Iceberg 功能、自动 compaction

    1.5 Hive 适用场景 vs 不适用场景

    ✅ 适用场景:

    • 大规模离线数据仓库(ETL、报表、数据分析)
    • PB 级数据的批量处理
    • 数据湖架构中的结构化查询层
    • BI 工具(Tableau、Power BI 等)通过 JDBC 对接大数据平台
    • 数据迁移和数据质量检查

    ❌ 不适用场景:

    • 在线事务处理(OLTP):延迟高(秒到分钟级),不适合实时交易
    • 低延迟查询(<100ms 响应):应使用 HBase、Druid、ClickHouse
    • 频繁的小数据量增删改:ACID 支持有限,效率低
    • 实时流数据处理:应使用 Apache Flink 或 Spark Streaming

    2. Hive 核心架构

    2.1 整体架构图

    ┌──────────────────────────────────────────────────────────────────┐
    │ Client 层 │
    │ CLI(hive shell) | Beeline(JDBC/ODBC)| Web UI | JDBC/ODBC │
    └───────────────────────────────┬──────────────────────────────────┘
    │ HQL 查询
    ▼
    ┌──────────────────────────────────────────────────────────────────┐
    │ HiveServer2 服务层 │
    │ Thrift Server(处理远程连接,支持多并发认证) │
    └───────────────────────────────┬──────────────────────────────────┘
    │
    ┌──────────────────────┼──────────────────────┐
    │ │ │
    ▼ ▼ ▼
    ┌──────────┐ ┌──────────┐ ┌──────────┐
    │ Driver │ │ Metastore│ │ Compiler │
    │(会话管理)│◄─────────►│(元数据) │◄─────────►│(查询解析)│
    └──────────┘ └──────────┘ └──────────┘
    │ │ │
    │ ▼ │
    │ ┌──────────────────┐ │
    │ │ RDBMS(MySQL等) │ │
    │ │ (持久化元数据) │ │
    │ └──────────────────┘ │
    │ │
    ▼ ┌────────────────────► │
    ┌──────────┐ │ ▼
    │Optimizer │◄────────────────┘ ┌──────────────┐
    │(查询优化)│ │ Execution │
    └──────────┘ │ Engine │
    │ MapReduce / │
    │ Tez /Spark │
    └──────┬───────┘
    │
    ┌───────────────────────┤
    │ │
    ▼ ▼
    ┌──────────┐ ┌──────────┐
    │ YARN │ │ HDFS │
    │(资源调度)│ │(数据存储)│
    └──────────┘ └──────────┘

    2.2 核心组件详解

    ① UI(用户界面)

    用户提交 HQL 查询和操作的入口,包括:

    • Hive CLI:命令行工具,已在 Hive 2.0 后被弃用,生产不推荐使用
    • Beeline:基于 JDBC 的客户端 CLI,通过 HiveServer2 连接,推荐使用
    • HWI(Web Interface):Web 界面,已废弃
    • JDBC/ODBC:通过 HiveServer2 对接 BI 工具和应用程序
    ② Driver(驱动)

    负责管理 HQL 语句的完整生命周期:

    • 接收来自 UI 的 HQL 语句
    • 创建和管理 Session Handle(会话句柄)
    • 提供 JDBC/ODBC 兼容接口
    • 协调 Compiler、Optimizer、Executor 的工作
    • 管理执行进度和结果获取
    ③ Compiler(编译器)

    HQL 语句的解析与编译核心:

  • 词法分析(Lexical Analysis):将 HQL 文本解析为 Token 序列
  • 语法分析(Parsing):生成 AST(Abstract Syntax Tree,抽象语法树)
  • 语义分析(Semantic Analysis):检查表名、列名、数据类型的合法性(查询 Metastore)
  • 逻辑计划生成(Logical Plan):将 AST 转换为算子树(Operator Tree)
  • 执行计划生成(Physical Plan):将逻辑计划转换为 DAG(有向无环图),分解为 MapReduce/Tez/Spark 的 Stage
  • HQL 文本 → Token → AST → Operator Tree → DAG of Stages → 物理执行计划

    ④ Optimizer(优化器)

    对编译器生成的执行计划进行变换优化:

    • 谓词下推(Predicate Pushdown):将过滤条件尽早执行,减少数据量
    • 列裁剪(Column Pruning):只读取查询中用到的列
    • 分区裁剪(Partition Pruning):根据分区条件跳过无关分区
    • Join 重排序(Join Reordering):将小表放在 Join 的驱动侧
    • 公共子表达式消除:避免重复计算
    • 使用 CBO(Cost-Based Optimizer):基于统计信息(ANALYZE TABLE)选择最优计划
    ⑤ Metastore(元数据存储)

    Hive 最重要的基础设施之一,存储所有表和分区的元数据:

    元数据类型内容
    数据库信息 数据库名、描述、HDFS 路径
    表信息 表名、列名、数据类型、注释、HDFS 位置、存储格式
    分区信息 分区键、分区值、对应 HDFS 路径
    SerDe 信息 序列化/反序列化类及属性
    统计信息 行数、列的 distinct 值数、最大/最小值等(ANALYZE TABLE 生成)

    Metastore 将元数据存储在关系型数据库(默认 Derby,生产用 MySQL/PostgreSQL)中,通过 Thrift 服务对外暴露。

    ⑥ Execution Engine(执行引擎)

    将优化后的执行计划提交给底层计算框架执行:

    • 与 YARN ResourceManager 交互,申请计算资源
    • 监控 Job 执行进度
    • 处理 Task 失败重试
    • 支持 MapReduce、Tez、Spark 三种引擎(可在会话级别切换)

    3. Hive 数据模型

    Hive 的数据模型层次从大到小为:Database → Table → Partition → Bucket

    3.1 Database(数据库)

    类似于关系型数据库中的 Schema,是表的命名空间。

    — 创建数据库(在 HDFS 中对应一个目录 /user/hive/warehouse/<db_name>.db/)
    CREATE DATABASE IF NOT EXISTS sales_db
    COMMENT 'Sales data warehouse'
    LOCATION '/data/hive/sales'
    WITH DBPROPERTIES ('creator'='admin', 'date'='2024-01-01');

    3.2 Table(表)

    Hive 中有两种核心表类型:

    内部表(Managed Table)

    默认表类型,Hive 完全管理数据的生命周期。
    DROP TABLE 时,HDFS 上的数据文件也会被删除。

    数据存储在 hive.metastore.warehouse.dir 配置的目录下(默认 /user/hive/warehouse/<db>/<table>/)。

    外部表(External Table)

    Hive 只管理元数据,不管理实际数据。
    DROP TABLE 时,只删除元数据,HDFS 上的数据文件不受影响。
    适合数据在 HDFS/S3 上已经存在、由其他工具管理的场景。

    3.3 Partition(分区)

    将表数据按某一列(分区键)的值划分到不同的 HDFS 子目录中,查询时通过分区裁剪跳过不相关数据:

    /user/hive/warehouse/orders/
    dt=2024-01-01/ ← 分区目录
    dt=2024-01-02/
    dt=2024-01-03/

    分区列不存储在数据文件中,而是体现在目录结构里。

    3.4 Bucket(桶/分桶)

    在分区(或表)的基础上,进一步将数据按某列的哈希值分散到固定数量的文件(桶)中:

    /user/hive/warehouse/orders/dt=2024-01-01/
    000000_0 ← 桶 0
    000001_0 ← 桶 1
    000002_0 ← 桶 2
    000003_0 ← 桶 3

    分桶的好处:

    • 高效 Bucket JOIN:两张表按相同列以相同桶数分桶,Join 时无需全表扫描
    • 高效 TABLESAMPLE:按桶抽样,效率远高于 RAND() 抽样
    • 数据均匀分布:避免数据倾斜

    4. 安装与环境配置

    4.1 前置条件

    依赖版本要求
    操作系统 Linux(Ubuntu 20.04+ / CentOS 7+)
    Java JDK 8(Hive 3.x)或 JDK 11/17/21(Hive 4.x)
    Hadoop 已安装运行的 Hadoop 集群(HDFS + YARN)
    数据库 Derby(测试)/ MySQL 5.7+(生产)/ PostgreSQL 12+(生产)
    内存 推荐 ≥ 8GB RAM

    4.2 二进制包安装(传统方式)

    步骤一:下载并解压 Hive

    # 从 https://hive.apache.org/downloads.html 获取最新版本
    # 以 Hive 3.1.3 为例
    wget https://downloads.apache.org/hive/hive-3.1.3/apache-hive-3.1.3-bin.tar.gz
    tar -xzf apache-hive-3.1.3-bin.tar.gz
    sudo mv apache-hive-3.1.3-bin /usr/local/hive

    步骤二:配置环境变量

    编辑 ~/.bashrc 或 /etc/profile,追加:

    export HIVE_HOME=/usr/local/hive
    export PATH=$PATH:$HIVE_HOME/bin
    export HIVE_CONF_DIR=$HIVE_HOME/conf

    source ~/.bashrc
    hive –version # 验证安装

    步骤三:创建 HDFS 仓库目录

    hdfs dfs -mkdir -p /user/hive/warehouse
    hdfs dfs -mkdir -p /tmp/hive
    hdfs dfs -chmod 777 /user/hive/warehouse
    hdfs dfs -chmod 777 /tmp/hive

    步骤四:配置 hive-site.xml

    cp $HIVE_HOME/conf/hive-default.xml.template $HIVE_HOME/conf/hive-site.xml
    vim $HIVE_HOME/conf/hive-site.xml

    最小化配置(使用嵌入式 Derby,仅用于测试):

    <configuration>
    <!– Hive 数据仓库在 HDFS 中的位置 –>
    <property>
    <name>hive.metastore.warehouse.dir</name>
    <value>/user/hive/warehouse</value>
    </property>

    <!– Hive 临时文件目录 –>
    <property>
    <name>hive.exec.scratchdir</name>
    <value>/tmp/hive</value>
    </property>

    <!– 执行引擎(mr | tez | spark) –>
    <property>
    <name>hive.execution.engine</name>
    <value>tez</value>
    </property>

    <!– 启用动态分区 –>
    <property>
    <name>hive.exec.dynamic.partition</name>
    <value>true</value>
    </property>
    <property>
    <name>hive.exec.dynamic.partition.mode</name>
    <value>nonstrict</value>
    </property>
    </configuration>

    步骤五:初始化 Schema(使用 Derby)

    # 初始化 Derby 元数据 Schema(只需执行一次)
    schematool -dbType derby -initSchema

    # 验证
    hive
    hive> SHOW DATABASES;


    4.3 配置 MySQL 作为 Metastore(生产推荐)

    步骤一:安装 MySQL 并创建元数据库

    sudo apt install -y mysql-server
    sudo mysql_secure_installation

    # 登录 MySQL 创建用户和数据库
    mysql -u root -p

    — 在 MySQL 中执行
    CREATE DATABASE metastore DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
    CREATE USER 'hive'@'%' IDENTIFIED BY 'hive_password';
    GRANT ALL PRIVILEGES ON metastore.* TO 'hive'@'%' WITH GRANT OPTION;
    FLUSH PRIVILEGES;
    EXIT;

    步骤二:添加 MySQL JDBC 驱动

    # 下载 MySQL Connector/J
    wget https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.33.tar.gz
    tar -xzf mysql-connector-java-8.0.33.tar.gz
    cp mysql-connector-java-8.0.33/mysql-connector-java-8.0.33.jar $HIVE_HOME/lib/

    步骤三:修改 hive-site.xml 指向 MySQL

    <configuration>
    <!– Hive 仓库目录 –>
    <property>
    <name>hive.metastore.warehouse.dir</name>
    <value>/user/hive/warehouse</value>
    </property>

    <!– MySQL 连接信息 –>
    <property>
    <name>javax.jdo.option.ConnectionURL</name>
    <value>jdbc:mysql://localhost:3306/metastore?createDatabaseIfNotExist=true&amp;useSSL=false&amp;serverTimezone=UTC</value>
    </property>
    <property>
    <name>javax.jdo.option.ConnectionDriverName</name>
    <value>com.mysql.cj.jdbc.Driver</value>
    </property>
    <property>
    <name>javax.jdo.option.ConnectionUserName</name>
    <value>hive</value>
    </property>
    <property>
    <name>javax.jdo.option.ConnectionPassword</name>
    <value>hive_password</value>
    </property>

    <!– Metastore 服务地址(远程模式) –>
    <property>
    <name>hive.metastore.uris</name>
    <value>thrift://localhost:9083</value>
    </property>

    <!– HiveServer2 配置 –>
    <property>
    <name>hive.server2.thrift.port</name>
    <value>10000</value>
    </property>
    <property>
    <name>hive.server2.thrift.bind.host</name>
    <value>0.0.0.0</value>
    </property>

    <!– 关闭 doAs(单用户测试时) –>
    <property>
    <name>hive.server2.enable.doAs</name>
    <value>false</value>
    </property>

    <!– 动态分区配置 –>
    <property>
    <name>hive.exec.dynamic.partition</name>
    <value>true</value>
    </property>
    <property>
    <name>hive.exec.dynamic.partition.mode</name>
    <value>nonstrict</value>
    </property>
    </configuration>

    步骤四:初始化 MySQL Metastore Schema

    schematool -dbType mysql -initSchema

    # 验证 schema 版本
    schematool -dbType mysql -info


    4.4 启动 Hive 服务

    # 1. 确保 Hadoop 已启动
    jps | grep -E "NameNode|DataNode|ResourceManager|NodeManager"

    # 2. 启动 Metastore 服务(后台运行)
    hive –service metastore &
    # 或
    nohup hive –service metastore > /tmp/metastore.log 2>&1 &

    # 验证 Metastore 是否在 9083 端口监听
    netstat -tuln | grep 9083

    # 3. 启动 HiveServer2(后台运行)
    hive –service hiveserver2 &
    # 或
    nohup hive –service hiveserver2 > /tmp/hiveserver2.log 2>&1 &

    # 验证 HiveServer2 是否在 10000 端口监听
    netstat -tuln | grep 10000

    # 4. 访问 HiveServer2 Web UI
    # http://localhost:10002


    4.5 Docker 快速启动(入门推荐)

    这是最快速的入门方式,官方提供完整 Docker 镜像:

    export HIVE_VERSION=4.0.1

    # 方式一:最简单,使用嵌入式 Derby,数据不持久化(快速体验)
    docker run -d -p 10000:10000 -p 10002:10002 \\
    –env SERVICE_NAME=hiveserver2 \\
    –name hive4 \\
    apache/hive:${HIVE_VERSION}

    # 连接到 Beeline
    docker exec -it hive4 beeline -u 'jdbc:hive2://localhost:10000/'

    # 方式二:使用 docker-compose,HiveServer2 + Metastore + PostgreSQL(数据持久化)
    # 创建 compose.yaml 文件
    cat > compose.yaml << 'EOF'
    version: "3"
    services:
    postgres:
    image: postgres:17.2
    environment:
    POSTGRES_PASSWORD: "hivepassword"
    POSTGRES_DB: "metastore"
    volumes:
    – postgres-data:/var/lib/postgresql/data

    metastore:
    image: apache/hive:4.0.1
    depends_on:
    – postgres
    environment:
    SERVICE_NAME: metastore
    DB_DRIVER: postgres
    SERVICE_OPTS: >-
    -Djavax.jdo.option.ConnectionDriverName=org.postgresql.Driver
    -Djavax.jdo.option.ConnectionURL=jdbc:postgresql://postgres:5432/metastore
    -Djavax.jdo.option.ConnectionUserName=postgres
    -Djavax.jdo.option.ConnectionPassword=hivepassword
    ports:
    – "9083:9083"

    hiveserver2:
    image: apache/hive:4.0.1
    depends_on:
    – metastore
    environment:
    SERVICE_NAME: hiveserver2
    IS_RESUME: "true"
    SERVICE_OPTS: "-Dhive.metastore.uris=thrift://metastore:9083"
    ports:
    – "10000:10000"
    – "10002:10002"
    volumes:
    – warehouse:/opt/hive/data/warehouse

    volumes:
    postgres-data:
    warehouse:
    EOF

    docker-compose up -d

    # 连接 Beeline
    docker exec -it hiveserver2-container beeline -u 'jdbc:hive2://localhost:10000/'


    5. HiveQL DDL 数据定义语言

    5.1 数据库操作

    — 创建数据库
    CREATE DATABASE IF NOT EXISTS mydb
    COMMENT '我的数据仓库'
    LOCATION '/data/hive/mydb'
    WITH DBPROPERTIES ('owner'='dataeng', 'version'='1.0');

    — 查看数据库列表
    SHOW DATABASES;
    SHOW DATABASES LIKE 'my*'; — 支持通配符

    — 查看数据库详情
    DESCRIBE DATABASE EXTENDED mydb;

    — 切换数据库
    USE mydb;

    — 删除数据库(CASCADE 同时删除表)
    DROP DATABASE IF EXISTS mydb CASCADE;

    — 修改数据库属性
    ALTER DATABASE mydb SET DBPROPERTIES ('updated_by'='admin');

    5.2 表的创建(内部表 vs 外部表)

    完整的 CREATE TABLE 语法

    CREATE [TEMPORARY] [EXTERNAL] TABLE [IF NOT EXISTS] [db_name.]table_name
    (
    col_name data_type [COMMENT 'column comment'],
    ...
    )
    [COMMENT 'table comment']
    [PARTITIONED BY (col_name data_type [COMMENT ...], ...)]
    [CLUSTERED BY (col_name, ...) [SORTED BY (col_name [ASC|DESC], ...)] INTO num_buckets BUCKETS]
    [ROW FORMAT row_format]
    [STORED AS file_format]
    [LOCATION 'hdfs_path']
    [TBLPROPERTIES (property_name=property_value, ...)]
    [AS select_statement]

    内部表示例

    — 基本内部表
    CREATE TABLE IF NOT EXISTS employees (
    emp_id INT COMMENT '员工ID',
    name STRING COMMENT '姓名',
    dept STRING COMMENT '部门',
    salary DOUBLE COMMENT '薪资',
    hire_date DATE COMMENT '入职日期',
    skills ARRAY<STRING> COMMENT '技能列表',
    address STRUCT<city:STRING, zip:STRING> COMMENT '地址'
    )
    COMMENT '员工信息表'
    ROW FORMAT DELIMITED
    FIELDS TERMINATED BY '\\t'
    COLLECTION ITEMS TERMINATED BY ','
    MAP KEYS TERMINATED BY ':'
    LINES TERMINATED BY '\\n'
    STORED AS TEXTFILE
    TBLPROPERTIES ('author'='admin', 'create_time'='2024-01-01');

    — 使用 ORC 格式(推荐生产使用)
    CREATE TABLE orders_orc (
    order_id BIGINT,
    user_id INT,
    amount DECIMAL(10,2),
    create_time TIMESTAMP
    )
    STORED AS ORC
    TBLPROPERTIES ('orc.compress'='SNAPPY');

    — 使用 CTAS(Create Table As Select)从已有表创建
    CREATE TABLE dept_summary
    STORED AS ORC
    AS
    SELECT dept, COUNT(*) AS cnt, AVG(salary) AS avg_salary
    FROM employees
    GROUP BY dept;

    外部表示例

    — 创建外部表,指向 HDFS 上已有数据
    CREATE EXTERNAL TABLE web_logs (
    ip STRING,
    log_time STRING,
    request STRING,
    status INT,
    bytes BIGINT
    )
    ROW FORMAT DELIMITED
    FIELDS TERMINATED BY ' '
    STORED AS TEXTFILE
    LOCATION '/data/weblogs/2024/'
    TBLPROPERTIES ('skip.header.line.count'='1'); — 跳过 CSV 头行

    — 外部表(Parquet 格式,指向 S3)
    CREATE EXTERNAL TABLE s3_events (
    event_id STRING,
    event_type STRING,
    user_id BIGINT,
    event_time TIMESTAMP
    )
    STORED AS PARQUET
    LOCATION 's3a://my-bucket/events/';

    查看表信息

    SHOW TABLES; — 列出所有表
    SHOW TABLES LIKE 'order*'; — 模糊查找
    DESCRIBE employees; — 查看表结构(列名、类型)
    DESCRIBE FORMATTED employees; — 查看详细信息(包括 HDFS 路径、格式等)
    DESCRIBE EXTENDED employees; — 查看更详细信息(包括原始元数据)
    SHOW CREATE TABLE employees; — 查看建表语句
    SHOW TBLPROPERTIES employees; — 查看表属性

    5.3 分区表

    — 创建分区表(按日期分区)
    CREATE TABLE user_events (
    user_id BIGINT,
    event_type STRING,
    event_time TIMESTAMP,
    page_url STRING
    )
    PARTITIONED BY (
    dt STRING COMMENT '日期分区,格式 yyyy-MM-dd',
    country STRING COMMENT '国家分区'
    )
    STORED AS ORC;

    — 手动添加分区(静态分区)
    ALTER TABLE user_events ADD PARTITION (dt='2024-01-01', country='CN')
    LOCATION '/data/events/dt=2024-01-01/country=CN';

    — 添加多个分区
    ALTER TABLE user_events ADD
    PARTITION (dt='2024-01-02', country='CN')
    PARTITION (dt='2024-01-02', country='US');

    — 删除分区(同时删除数据,如果是内部表)
    ALTER TABLE user_events DROP PARTITION (dt='2023-12-01');
    ALTER TABLE user_events DROP PARTITION (dt < '2023-01-01'); — 按条件批量删除

    — 查看分区列表
    SHOW PARTITIONS user_events;
    SHOW PARTITIONS user_events PARTITION (dt='2024-01-01');

    — 修复分区(当 HDFS 目录已存在但 Metastore 没有记录时)
    MSCK REPAIR TABLE user_events;

    — 查询时分区裁剪(必须加分区条件,否则全表扫描)
    SELECT COUNT(*) FROM user_events WHERE dt='2024-01-01' AND country='CN';

    5.4 分桶表

    — 创建分桶表(按 user_id 哈希分为 32 个桶)
    CREATE TABLE user_orders (
    order_id BIGINT,
    user_id INT,
    amount DOUBLE,
    status STRING
    )
    CLUSTERED BY (user_id) SORTED BY (order_id ASC) INTO 32 BUCKETS
    STORED AS ORC;

    — 同时使用分区和分桶
    CREATE TABLE user_behavior (
    user_id BIGINT,
    action STRING,
    item_id BIGINT
    )
    PARTITIONED BY (dt STRING)
    CLUSTERED BY (user_id) INTO 256 BUCKETS
    STORED AS ORC;

    — 向分桶表插入数据(必须启用 bucketing 支持)
    SET hive.enforce.bucketing = true; — Hive 1.x 需要,2.x+ 已默认
    INSERT INTO user_orders SELECT order_id, user_id, amount, status FROM raw_orders;

    — 分桶采样查询
    SELECT * FROM user_orders TABLESAMPLE(BUCKET 1 OUT OF 32 ON user_id); — 取第1个桶
    SELECT * FROM user_orders TABLESAMPLE(BUCKET 1 OUT OF 8 ON user_id); — 取前4个桶(32/8=4)

    5.5 表结构修改

    — 重命名表
    ALTER TABLE employees RENAME TO staff;

    — 添加列
    ALTER TABLE employees ADD COLUMNS (
    phone STRING COMMENT '手机号',
    email STRING COMMENT '邮箱'
    );

    — 修改列(改名/改类型)
    ALTER TABLE employees CHANGE COLUMN name full_name STRING COMMENT '全名';

    — 替换所有列(重新定义列结构)
    ALTER TABLE employees REPLACE COLUMNS (
    emp_id INT,
    full_name STRING,
    salary DOUBLE
    );

    — 修改表属性
    ALTER TABLE employees SET TBLPROPERTIES ('last_modified_by'='admin');

    — 修改存储格式
    ALTER TABLE employees SET FILEFORMAT ORC;

    — 修改表位置
    ALTER TABLE employees SET LOCATION '/new/hdfs/path/';

    — 分区表修改分区属性
    ALTER TABLE user_events PARTITION (dt='2024-01-01') SET FILEFORMAT ORC;

    — 合并小文件(ORC 格式支持)
    ALTER TABLE user_events PARTITION (dt='2024-01-01') CONCATENATE;

    5.6 视图(View)

    — 创建视图
    CREATE VIEW IF NOT EXISTS active_employees AS
    SELECT emp_id, name, dept, salary
    FROM employees
    WHERE hire_date > '2020-01-01' AND salary > 5000;

    — 查询视图(和查询普通表一样)
    SELECT dept, COUNT(*) FROM active_employees GROUP BY dept;

    — 修改视图
    ALTER VIEW active_employees AS
    SELECT emp_id, name, dept, salary, hire_date
    FROM employees
    WHERE salary > 8000;

    — 删除视图
    DROP VIEW IF EXISTS active_employees;

    — 物化视图(Hive 3.0+,需要 ACID)
    CREATE MATERIALIZED VIEW emp_dept_summary
    AS SELECT dept, COUNT(*) cnt, AVG(salary) avg_sal
    FROM employees GROUP BY dept;

    — 重建物化视图(更新缓存)
    ALTER MATERIALIZED VIEW emp_dept_summary REBUILD;


    6. HiveQL DML 数据操作语言

    6.1 数据加载(LOAD DATA)

    — 从本地文件系统加载(LOCAL 关键字表示本地文件)
    — 注意:会将文件移动/复制到 HDFS 仓库目录
    LOAD DATA LOCAL INPATH '/home/user/data/employees.csv'
    INTO TABLE employees;

    — 加载并覆盖现有数据
    LOAD DATA LOCAL INPATH '/home/user/data/employees.csv'
    OVERWRITE INTO TABLE employees;

    — 从 HDFS 加载(不加 LOCAL,文件从 HDFS 移动到表目录)
    LOAD DATA INPATH '/data/raw/employees.csv'
    INTO TABLE employees;

    — 加载数据到特定分区
    LOAD DATA LOCAL INPATH '/data/events_20240101.csv'
    INTO TABLE user_events PARTITION (dt='2024-01-01', country='CN');

    注意:LOAD DATA 是纯文件移动操作,不进行 MapReduce,速度很快。它不会验证数据格式和类型。

    6.2 INSERT 语句

    — INSERT INTO(追加数据)
    INSERT INTO TABLE employees VALUES
    (1001, 'Alice', 'Engineering', 12000.00, '2022-03-15'),
    (1002, 'Bob', 'Marketing', 9500.00, '2021-07-01');

    — INSERT OVERWRITE(覆盖数据)
    INSERT OVERWRITE TABLE dept_summary
    SELECT dept, COUNT(*) cnt, AVG(salary) avg_sal
    FROM employees GROUP BY dept;

    — 动态分区插入(自动根据查询结果创建分区)
    SET hive.exec.dynamic.partition.mode = nonstrict;
    INSERT OVERWRITE TABLE user_events PARTITION (dt, country)
    SELECT user_id, event_type, event_time, page_url, dt, country
    FROM raw_events
    WHERE dt >= '2024-01-01';

    — 多目标插入(一次扫描,写多张表,性能优化技巧)
    FROM employees
    INSERT OVERWRITE TABLE high_salary_emp
    SELECT * WHERE salary > 15000
    INSERT INTO TABLE mid_salary_emp
    SELECT * WHERE salary BETWEEN 8000 AND 15000
    INSERT INTO TABLE low_salary_emp
    SELECT * WHERE salary < 8000;

    — INSERT INTO … SELECT(从查询结果插入)
    INSERT INTO TABLE orders_backup
    SELECT * FROM orders WHERE YEAR(create_time) = 2023;

    6.3 SELECT 查询详解

    — 基本查询
    SELECT emp_id, name, salary
    FROM employees
    WHERE dept = 'Engineering' AND salary > 10000
    ORDER BY salary DESC
    LIMIT 10;

    — 聚合查询
    SELECT dept,
    COUNT(*) AS employee_count,
    AVG(salary) AS avg_salary,
    MAX(salary) AS max_salary,
    MIN(salary) AS min_salary,
    SUM(salary) AS total_salary
    FROM employees
    GROUP BY dept
    HAVING COUNT(*) > 5
    ORDER BY avg_salary DESC;

    — DISTINCT
    SELECT DISTINCT dept FROM employees;
    SELECT COUNT(DISTINCT dept) FROM employees; — 统计唯一部门数

    — 正则表达式查询(REGEXP / RLIKE)
    SELECT name FROM employees WHERE name RLIKE '^A.*';
    SELECT name FROM employees WHERE name REGEXP 'Alice|Bob';

    — LIKE 模糊查询
    SELECT name FROM employees WHERE name LIKE 'A%';
    SELECT name FROM employees WHERE name LIKE '_ob'; — 下划线匹配单个字符

    — BETWEEN … AND
    SELECT * FROM employees WHERE salary BETWEEN 8000 AND 12000;

    — IN 子句
    SELECT * FROM employees WHERE dept IN ('Engineering', 'Marketing', 'Finance');

    — IS NULL / IS NOT NULL
    SELECT * FROM employees WHERE email IS NULL;

    — CASE WHEN
    SELECT name,
    salary,
    CASE
    WHEN salary >= 15000 THEN '高薪'
    WHEN salary >= 10000 THEN '中薪'
    ELSE '低薪'
    END AS salary_level
    FROM employees;

    — SORT BY vs ORDER BY vs DISTRIBUTE BY vs CLUSTER BY
    — ORDER BY: 全局排序(只有一个 Reducer),大数据量慎用
    SELECT * FROM employees ORDER BY salary DESC;

    — SORT BY: 每个 Reducer 内部排序(局部有序)
    SELECT * FROM employees SORT BY salary DESC;

    — DISTRIBUTE BY: 按指定列分发到 Reducer(常与 SORT BY 配合)
    SELECT * FROM employees DISTRIBUTE BY dept SORT BY dept, salary DESC;

    — CLUSTER BY: 等价于 DISTRIBUTE BY col SORT BY col(相同列升序)
    SELECT * FROM employees CLUSTER BY dept;

    — LIMIT 与 OFFSET
    SELECT * FROM employees ORDER BY salary DESC LIMIT 10;
    SELECT * FROM employees ORDER BY salary DESC LIMIT 10 OFFSET 20; — 第 21-30 条

    — TABLESAMPLE 数据采样
    SELECT * FROM employees TABLESAMPLE(10 PERCENT); — 随机采样 10%
    SELECT * FROM employees TABLESAMPLE(1000 ROWS); — 采样 1000 行
    SELECT * FROM user_orders TABLESAMPLE(BUCKET 2 OUT OF 32 ON user_id); — 桶采样

    — LATERAL VIEW EXPLODE(展开数组/Map 列)
    SELECT emp_id, name, skill
    FROM employees
    LATERAL VIEW EXPLODE(skills) tmp AS skill;

    — LATERAL VIEW json_tuple(解析 JSON)
    SELECT base.id, jt.name, jt.age
    FROM json_table base
    LATERAL VIEW json_tuple(base.json_col, 'name', 'age') jt AS name, age;

    6.4 JOIN 操作

    — INNER JOIN
    SELECT e.name, e.salary, d.dept_name, d.location
    FROM employees e
    INNER JOIN departments d ON e.dept = d.dept_id;

    — LEFT OUTER JOIN
    SELECT e.name, d.dept_name
    FROM employees e
    LEFT JOIN departments d ON e.dept = d.dept_id;

    — RIGHT OUTER JOIN
    SELECT e.name, d.dept_name
    FROM employees e
    RIGHT JOIN departments d ON e.dept = d.dept_id;

    — FULL OUTER JOIN
    SELECT e.name, d.dept_name
    FROM employees e
    FULL OUTER JOIN departments d ON e.dept = d.dept_id;

    — CROSS JOIN(笛卡尔积,谨慎使用!)
    SELECT e.name, d.dept_name
    FROM employees e CROSS JOIN departments d;

    — LEFT SEMI JOIN(相当于 EXISTS,效率高于子查询)
    SELECT e.*
    FROM employees e
    LEFT SEMI JOIN high_salary_list h ON e.emp_id = h.emp_id;

    — MAP JOIN(小表 JOIN,广播到所有 Map 端,避免 Reduce)
    — 自动触发条件:hive.auto.convert.join=true 且小表 < hive.mapjoin.smalltable.filesize
    SELECT /*+ MAPJOIN(d) */
    e.name, d.dept_name
    FROM employees e
    JOIN departments d ON e.dept = d.dept_id;

    — Bucket Map Join(两张表均按相同列分桶时效率最高)
    — 需要设置:set hive.optimize.bucketmapjoin=true

    6.5 子查询与 CTE

    — 子查询(IN)
    SELECT * FROM employees
    WHERE dept IN (
    SELECT dept_id FROM departments WHERE location = 'Beijing'
    );

    — 子查询(EXISTS)
    SELECT * FROM employees e
    WHERE EXISTS (
    SELECT 1 FROM high_performers h WHERE h.emp_id = e.emp_id
    );

    — FROM 子句中的子查询
    SELECT dept, avg_sal
    FROM (
    SELECT dept, AVG(salary) AS avg_sal
    FROM employees
    GROUP BY dept
    ) t
    WHERE avg_sal > 10000;

    — CTE(Common Table Expression,WITH 子句)—— Hive 0.13+
    WITH
    dept_stats AS (
    SELECT dept, COUNT(*) cnt, AVG(salary) avg_sal
    FROM employees
    GROUP BY dept
    ),
    high_dept AS (
    SELECT dept FROM dept_stats WHERE avg_sal > 10000
    )
    SELECT e.name, e.salary, e.dept
    FROM employees e
    JOIN high_dept h ON e.dept = h.dept;

    6.6 窗口函数(Window Functions)

    窗口函数是 Hive 中非常强大的分析工具:

    — 语法:function() OVER ([PARTITION BY …] [ORDER BY …] [frame_clause])

    — ROW_NUMBER:每行一个唯一序号
    SELECT name, dept, salary,
    ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn
    FROM employees;

    — RANK:允许并列,跳号(1,1,3)
    SELECT name, dept, salary,
    RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS rnk
    FROM employees;

    — DENSE_RANK:允许并列,不跳号(1,1,2)
    SELECT name, dept, salary,
    DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS dense_rnk
    FROM employees;

    — 取每个部门工资前3名(ROW_NUMBER 去重)
    SELECT * FROM (
    SELECT name, dept, salary,
    ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn
    FROM employees
    ) t WHERE rn <= 3;

    — LAG / LEAD:访问前/后 N 行数据
    SELECT name, salary,
    LAG(salary, 1, 0) OVER (PARTITION BY dept ORDER BY hire_date) AS prev_salary,
    LEAD(salary, 1, 0) OVER (PARTITION BY dept ORDER BY hire_date) AS next_salary
    FROM employees;

    — FIRST_VALUE / LAST_VALUE
    SELECT name, dept, salary,
    FIRST_VALUE(name) OVER (PARTITION BY dept ORDER BY salary DESC) AS top_earner
    FROM employees;

    — SUM/AVG/COUNT 累计汇总
    SELECT name, dept, salary,
    SUM(salary) OVER (PARTITION BY dept ORDER BY hire_date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS running_total,
    AVG(salary) OVER (PARTITION BY dept) AS dept_avg,
    COUNT(*) OVER () AS total_employees
    FROM employees;

    — NTILE:将数据分成 N 等份
    SELECT name, salary,
    NTILE(4) OVER (ORDER BY salary) AS quartile
    FROM employees;

    — PERCENT_RANK / CUME_DIST
    SELECT name, salary,
    PERCENT_RANK() OVER (ORDER BY salary) AS pct_rank,
    CUME_DIST() OVER (ORDER BY salary) AS cume_dist
    FROM employees;

    — 帧规范(Frame Specification)
    — ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW → 从头到当前行
    — ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING → 前2行到后2行(滑动窗口)
    — RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING → 当前行到末尾
    SELECT name, salary,
    AVG(salary) OVER (
    PARTITION BY dept
    ORDER BY hire_date
    ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING
    ) AS moving_avg
    FROM employees;

    6.7 ACID 事务(UPDATE / DELETE)

    Hive 0.14+ 支持行级别的 UPDATE/DELETE,但需要满足以下条件:

    — 前置配置(hive-site.xml 或 SET 命令)
    SET hive.support.concurrency = true;
    SET hive.enforce.bucketing = true;
    SET hive.exec.dynamic.partition.mode = nonstrict;
    SET hive.txn.manager = org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
    SET hive.compactor.initiator.on = true;
    SET hive.compactor.worker.threads = 1;

    — 建表必须使用 ORC 格式 + TRANSACTIONAL 属性
    CREATE TABLE student (
    id INT,
    name STRING,
    score INT
    )
    CLUSTERED BY (id) INTO 4 BUCKETS
    STORED AS ORC
    TBLPROPERTIES ('transactional'='true');

    — UPDATE 语句
    UPDATE student SET score = 95 WHERE id = 1001;
    UPDATE student SET name = 'Alice Zhang', score = score + 5 WHERE name = 'Alice';

    — DELETE 语句
    DELETE FROM student WHERE id = 1005;
    DELETE FROM student WHERE score < 60;

    — MERGE(Hive 2.2+,Upsert 操作)
    MERGE INTO student AS target
    USING updates AS source
    ON target.id = source.id
    WHEN MATCHED AND source.action = 'UPDATE' THEN
    UPDATE SET name = source.name, score = source.score
    WHEN MATCHED AND source.action = 'DELETE' THEN DELETE
    WHEN NOT MATCHED THEN
    INSERT VALUES (source.id, source.name, source.score);


    7. Hive 数据类型详解

    7.1 基本数据类型

    类型字节范围/说明示例
    TINYINT 1B -128 ~ 127 100Y
    SMALLINT 2B -32768 ~ 32767 1000S
    INT / INTEGER 4B -2^31 ~ 2^31-1 100
    BIGINT 8B -2^63 ~ 2^63-1 100L
    FLOAT 4B 单精度浮点数 3.14
    DOUBLE 8B 双精度浮点数 3.14159265
    DECIMAL(p,s) 可变 精确小数,p 总精度,s 小数位 DECIMAL(10,2)
    BOOLEAN – TRUE / FALSE true
    STRING 可变 无长度限制的字符串(UTF-8) 'hello'
    VARCHAR(n) 可变 最大长度 n 的字符串 VARCHAR(255)
    CHAR(n) 固定 固定长度字符串,不足补空格 CHAR(10)
    BINARY 可变 字节数组 –
    TIMESTAMP – 纳秒精度时间戳 '2024-01-01 12:00:00'
    DATE – 仅日期(无时间) '2024-01-01'
    INTERVAL – 时间间隔 INTERVAL '1' DAY

    7.2 复杂数据类型

    类型语法说明示例
    ARRAY ARRAY<data_type> 有序列表,下标从 0 开始 ['a','b','c']
    MAP MAP<key_type, val_type> 键值对,key 必须是基本类型 {'k1':1,'k2':2}
    STRUCT STRUCT<name:type,…> 命名字段的结构体 {'name':'Alice','age':30}
    UNIONTYPE UNIONTYPE<t1,t2,…> 联合类型(较少使用) –

    — 复杂类型的使用示例
    CREATE TABLE complex_example (
    id INT,
    tags ARRAY<STRING>, — 数组
    props MAP<STRING, STRING>, — Map
    address STRUCT<city:STRING, zip:STRING, country:STRING> — 结构体
    );

    — 插入复杂类型数据
    INSERT INTO complex_example VALUES (
    1,
    ARRAY('hive', 'hadoop', 'spark'),
    MAP('color', 'blue', 'size', 'L'),
    NAMED_STRUCT('city', 'Beijing', 'zip', '100000', 'country', 'CN')
    );

    — 访问复杂类型
    SELECT
    id,
    tags[0] AS first_tag, — 数组下标访问
    tags[1] AS second_tag,
    SIZE(tags) AS tag_count, — 数组大小
    props['color'] AS color, — Map 键访问
    address.city AS city, — Struct 字段访问
    address.zip AS zip
    FROM complex_example;

    — EXPLODE 展开数组
    SELECT id, tag
    FROM complex_example
    LATERAL VIEW EXPLODE(tags) tmp AS tag;

    — EXPLODE 展开 Map
    SELECT id, k, v
    FROM complex_example
    LATERAL VIEW EXPLODE(props) tmp AS k, v;

    7.3 类型转换

    — 隐式转换(自动类型提升:TINYINT → SMALLINT → INT → BIGINT → FLOAT → DOUBLE)
    SELECT 1 + 1.5; — 自动转为 DOUBLE

    — 显式转换(CAST)
    SELECT CAST('123' AS INT);
    SELECT CAST(3.14 AS INT); — 截断 → 3
    SELECT CAST('2024-01-01' AS DATE);
    SELECT CAST(salary AS STRING) FROM employees;

    — 字符串与数字转换
    SELECT CAST('123abc' AS INT); — 返回 NULL(无法转换)

    — 日期类型转换
    SELECT TO_DATE('2024-01-15 12:30:00'); — → '2024-01-15'
    SELECT UNIX_TIMESTAMP('2024-01-01 00:00:00', 'yyyy-MM-dd HH:mm:ss'); — → 秒级时间戳
    SELECT FROM_UNIXTIME(1704067200, 'yyyy-MM-dd HH:mm:ss'); — 时间戳 → 字符串


    8. Hive 文件格式与存储

    8.1 支持的文件格式对比

    格式存储方式压缩支持查询性能写入性能适用场景
    TextFile 行式,纯文本 gzip/bzip2 等 差 快 数据交换、调试、原始日志
    SequenceFile 行式,二进制 Block/Record 一般 一般 Hadoop 原生,历史遗留
    RCFile 列式,行组 支持 中等 一般 旧系统
    ORC 列式(带索引) Zlib/Snappy/LZ4 极好 中等 生产推荐:分析型查询
    Parquet 列式 Gzip/Snappy/LZ4 极好 中等 生产推荐:与 Spark 互通
    Avro 行式,带 Schema Deflate/Snappy 中等 快 数据序列化、Kafka 数据落地

    8.2 ORC 格式详解(推荐)

    ORC(Optimized Row Columnar)是 Hive 原生的高性能列式文件格式:

    ORC 文件结构:

    ORC 文件
    ├── Stripe 1(默认 64MB)
    │ ├── Index Data(轻量级索引,每 10000 行一个)
    │ ├── Row Data(实际列数据)
    │ └── Stripe Footer(列统计信息)
    ├── Stripe 2
    │ └── …
    └── File Footer
    ├── 文件级统计信息(行数、列最大/最小值等)
    └── Stripe 位置信息

    ORC 的核心优化:

    • 列投影(Column Projection):只读取查询涉及的列
    • 谓词下推(Predicate Pushdown):利用 Stripe/Row Group 统计信息跳过无关数据
    • Bloom Filter 索引:快速判断某个 Stripe 是否包含目标值
    • Run-Length Encoding(RLE):对整数列压缩效果极好
    • Dictionary Encoding:对低基数字符串列压缩率极高

    — 使用 ORC 格式建表
    CREATE TABLE sales (
    sale_id BIGINT,
    product STRING,
    amount DECIMAL(12,2),
    sale_date DATE
    )
    STORED AS ORC
    TBLPROPERTIES (
    'orc.compress'='SNAPPY', — 压缩算法:NONE/ZLIB/SNAPPY/LZ4(推荐 SNAPPY)
    'orc.stripe.size'='67108864', — Stripe 大小 64MB
    'orc.row.index.stride'='10000', — 行组索引步长
    'orc.create.index'='true' — 启用行组索引
    );

    — 将 TextFile 表转换为 ORC
    CREATE TABLE sales_orc STORED AS ORC AS SELECT * FROM sales_text;

    8.3 Parquet 格式详解

    Parquet 是跨语言的通用列式格式,与 Spark、Impala、Presto 互通性最好:

    — 使用 Parquet 建表
    CREATE TABLE events_parquet (
    event_id STRING,
    user_id BIGINT,
    event_type STRING,
    ts TIMESTAMP
    )
    STORED AS PARQUET
    TBLPROPERTIES (
    'parquet.compression'='SNAPPY' — UNCOMPRESSED/GZIP/SNAPPY/LZO/BROTLI/LZ4
    );

    8.4 压缩配置

    — 开启中间结果(Map 输出)压缩
    SET hive.exec.compress.intermediate=true;
    SET mapreduce.map.output.compress=true;
    SET mapreduce.map.output.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;

    — 开启最终输出压缩
    SET hive.exec.compress.output=true;
    SET mapreduce.output.fileoutputformat.compress=true;
    SET mapreduce.output.fileoutputformat.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;
    SET mapreduce.output.fileoutputformat.compress.type=BLOCK;

    — Tez 引擎中间数据压缩
    SET tez.runtime.compress=true;
    SET tez.runtime.compress.codec=org.apache.hadoop.io.compress.SnappyCodec;


    9. SerDe(Serialization / Deserialization)

    SerDe 是 Hive 读写文件的核心接口,决定了 Hive 如何解析和序列化数据。

    9.1 常用内置 SerDe

    LazySimpleSerDe(默认)

    — 解析分隔符文本
    CREATE TABLE csv_data (
    id INT,
    name STRING,
    age INT
    )
    ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
    WITH SERDEPROPERTIES (
    'field.delim'=',',
    'line.delim'='\\n',
    'null.format'='\\\\N'
    )
    STORED AS TEXTFILE;

    — 简写方式(等价于上面)
    CREATE TABLE csv_data2 (id INT, name STRING, age INT)
    ROW FORMAT DELIMITED
    FIELDS TERMINATED BY ','
    LINES TERMINATED BY '\\n'
    NULL DEFINED AS '\\\\N'
    STORED AS TEXTFILE;

    JsonSerDe

    — 解析 JSON 格式文件(每行一个 JSON)
    CREATE TABLE json_logs (
    user_id INT,
    action STRING,
    timestamp BIGINT,
    metadata MAP<STRING, STRING>
    )
    ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe'
    STORED AS TEXTFILE;

    RegexSerDe(正则表达式)

    — 用正则表达式解析复杂格式(如 Apache 日志)
    CREATE TABLE apache_logs (
    ip STRING,
    identity STRING,
    user STRING,
    time STRING,
    request STRING,
    status INT,
    size INT
    )
    ROW FORMAT SERDE 'org.apache.hadoop.hive.contrib.serde2.RegexSerDe'
    WITH SERDEPROPERTIES (
    'input.regex' = '([^ ]*) ([^ ]*) ([^ ]*) \\\\[([^\\\\]]*)\\\\] "([^"]*)" ([0-9]*) ([0-9]*)'
    )
    STORED AS TEXTFILE;

    OpenCSVSerde

    — 处理包含转义字符的复杂 CSV
    CREATE TABLE complex_csv (
    id STRING,
    name STRING,
    desc STRING
    )
    ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
    WITH SERDEPROPERTIES (
    'separatorChar'=',',
    'quoteChar'='"',
    'escapeChar'='\\\\'
    )
    STORED AS TEXTFILE;


    10. Hive 内置函数大全

    10.1 字符串函数

    — 基本操作
    SELECT LENGTH('hello world'); — 11
    SELECT LOWER('Hello WORLD'); — hello world
    SELECT UPPER('hello world'); — HELLO WORLD
    SELECT TRIM(' hello '); — hello
    SELECT LTRIM(' hello '); — 'hello '
    SELECT RTRIM(' hello '); — ' hello'

    — 截取与拼接
    SELECT SUBSTR('hello world', 1, 5); — hello(下标从 1 开始)
    SELECT SUBSTRING('hello world', 7); — world
    SELECT CONCAT('hello', ' ', 'world'); — hello world
    SELECT CONCAT_WS('-', 'a', 'b', 'c'); — a-b-c(带分隔符)

    — 查找与替换
    SELECT INSTR('hello world', 'world'); — 7(位置)
    SELECT LOCATE('world', 'hello world'); — 7
    SELECT REPLACE('hello world', 'world', 'hive'); — hello hive
    SELECT REGEXP_REPLACE('abc123def', '[0-9]+', 'NUM'); — abcNUMdef
    SELECT REGEXP_EXTRACT('abc123def', '[0-9]+', 0); — 123

    — 分割与拼接
    SELECT SPLIT('a,b,c', ','); — ["a","b","c"](返回数组)
    SELECT SPLIT('a,b,c', ',')[1]; — b(取第2个)

    — 格式化
    SELECT LPAD('5', 4, '0'); — 0005(左填充)
    SELECT RPAD('5', 4, '0'); — 5000(右填充)
    SELECT PRINTF('%05d', 42); — 00042
    SELECT FORMAT_NUMBER(1234567.89, 2); — 1,234,567.89

    — 字符串判断
    SELECT LIKE('hello', 'hel%'); — true
    SELECT RLIKE('hello123', '[a-z]+[0-9]+'); — true

    — 其他
    SELECT REVERSE('hello'); — olleh
    SELECT REPEAT('ab', 3); — ababab
    SELECT SPACE(5); — ' '(5 个空格)
    SELECT ASCII('A'); — 65
    SELECT CHR(65); — A
    SELECT QUOTE('it''s'); — 'it\\'s'
    SELECT INITCAP('hello world'); — Hello World

    10.2 数学函数

    SELECT ROUND(3.567, 2); — 3.57
    SELECT FLOOR(3.7); — 3
    SELECT CEIL(3.2); — 4
    SELECT ABS(–5); — 5
    SELECT SQRT(16); — 4.0
    SELECT POWER(2, 10); — 1024.0
    SELECT LOG(10, 100); — 2.0(log 以 10 为底)
    SELECT LN(2.718281); — ≈1.0
    SELECT EXP(1); — ≈2.718
    SELECT MOD(10, 3); — 1
    SELECT SIGN(–5); — -1(正数1,负数-1,零0)
    SELECT PI(); — 3.141592653589793
    SELECT SIN(0), COS(0), TAN(0); — 0.0, 1.0, 0.0
    SELECT RAND(); — 0~1 随机数
    SELECT RAND(42); — 固定种子的随机数
    SELECT GREATEST(3, 1, 4, 1, 5, 9); — 9
    SELECT LEAST(3, 1, 4, 1, 5, 9); — 1
    SELECT FACTORIAL(5); — 120
    SELECT SHIFTLEFT(8, 2); — 32(位运算左移)
    SELECT SHIFTRIGHT(32, 2); — 8(位运算右移)
    SELECT HEX(255); — FF
    SELECT UNHEX('FF'); — 255

    10.3 日期和时间函数

    — 获取当前时间
    SELECT CURRENT_DATE(); — 2024-01-01
    SELECT CURRENT_TIMESTAMP(); — 2024-01-01 12:00:00.000
    SELECT NOW(); — 等价于 CURRENT_TIMESTAMP()
    SELECT UNIX_TIMESTAMP(); — 当前 Unix 时间戳(秒)

    — 日期解析与格式化
    SELECT TO_DATE('2024-01-15 12:30:00'); — 2024-01-15
    SELECT DATE_FORMAT('2024-01-15', 'yyyyMMdd'); — 20240115
    SELECT UNIX_TIMESTAMP('2024-01-01', 'yyyy-MM-dd'); — → 1704067200
    SELECT FROM_UNIXTIME(1704067200); — 2024-01-01 00:00:00
    SELECT FROM_UNIXTIME(1704067200, 'yyyy-MM-dd'); — 2024-01-01

    — 日期提取
    SELECT YEAR('2024-01-15'); — 2024
    SELECT MONTH('2024-01-15'); — 1
    SELECT DAY('2024-01-15'); — 15
    SELECT HOUR('2024-01-15 12:30:45'); — 12
    SELECT MINUTE('2024-01-15 12:30:45'); — 30
    SELECT SECOND('2024-01-15 12:30:45'); — 45
    SELECT WEEKOFYEAR('2024-01-15'); — 3(第3周)
    SELECT DAYOFWEEK('2024-01-15'); — 2(1=周日,2=周一…)
    SELECT QUARTER('2024-04-15'); — 2

    — 日期运算
    SELECT DATE_ADD('2024-01-15', 10); — 2024-01-25
    SELECT DATE_SUB('2024-01-15', 10); — 2024-01-05
    SELECT DATEDIFF('2024-01-15', '2024-01-01'); — 14(天数差)
    SELECT ADD_MONTHS('2024-01-15', 2); — 2024-03-15
    SELECT LAST_DAY('2024-02-01'); — 2024-02-29(当月最后一天)
    SELECT NEXT_DAY('2024-01-15', 'Monday'); — 下一个星期一

    — 日期截断
    SELECT TRUNC('2024-01-15', 'MM'); — 2024-01-01(月初)
    SELECT TRUNC('2024-01-15', 'YY'); — 2024-01-01(年初)
    SELECT DATE_TRUNC('month', '2024-01-15 12:30:00'); — 2024-01-01 00:00:00

    — 日期比较
    SELECT GREATEST('2024-01-15', '2023-12-31'); — 2024-01-15

    10.4 条件函数

    — NVL / COALESCE(空值处理)
    SELECT NVL(NULL, 'default'); — default
    SELECT NVL(null_col, 0) FROM table; — 替换 NULL 为 0
    SELECT COALESCE(a, b, c, 'none'); — 返回第一个非 NULL 值

    — IF
    SELECT IF(salary > 10000, '高薪', '低薪') FROM employees;

    — IFF(Hive 2.0+)
    SELECT IFF(score >= 60, 'pass', 'fail') FROM students;

    — NULLIF(相等则返回 NULL)
    SELECT NULLIF(a, b); — 若 a=b 则返回 NULL,否则返回 a

    — CASE WHEN(见查询章节)

    — ISNULL / ISNOTNULL
    SELECT ISNULL(null_col) FROM table; — true/false

    — NVL2
    SELECT NVL2(email, '有邮箱', '无邮箱') FROM employees;

    — DECODE(Oracle 兼容)
    SELECT DECODE(status, 1, '有效', 0, '无效', '未知') FROM orders;

    10.5 聚合函数

    SELECT
    COUNT(*) AS total_rows,
    COUNT(email) AS non_null_emails, — 不统计 NULL
    COUNT(DISTINCT dept) AS unique_depts,
    SUM(salary) AS total_salary,
    AVG(salary) AS avg_salary,
    MAX(salary) AS max_salary,
    MIN(salary) AS min_salary,
    STDDEV_POP(salary) AS std_salary, — 标准差(总体)
    VARIANCE(salary) AS var_salary, — 方差
    COLLECT_SET(dept) AS dept_set, — 收集唯一值到数组
    COLLECT_LIST(dept) AS dept_list, — 收集所有值到数组(含重复)
    PERCENTILE(salary, 0.5) AS median, — 中位数(数值列)
    PERCENTILE_APPROX(salary, 0.5) AS approx_median — 近似中位数(大数据)
    FROM employees;

    — GROUP_CONCAT(类似 MySQL 的 GROUP_CONCAT)
    SELECT dept, CONCAT_WS(',', COLLECT_LIST(name)) AS member_names
    FROM employees
    GROUP BY dept;

    — GROUPING SETS / CUBE / ROLLUP(多维聚合)
    — ROLLUP(层级聚合,等于多个 GROUP BY 结果的 UNION)
    SELECT dept, job_level, SUM(salary)
    FROM employees
    GROUP BY dept, job_level WITH ROLLUP;

    — CUBE(所有维度组合)
    SELECT dept, year, SUM(salary)
    FROM employees
    GROUP BY dept, year WITH CUBE;

    — GROUPING SETS(指定聚合维度)
    SELECT dept, country, SUM(salary)
    FROM employees
    GROUP BY dept, country
    GROUPING SETS ((dept, country), (dept), (country), ());

    10.6 集合函数

    SELECT
    SIZE(tags) AS tag_count, — 数组/Map 的大小
    ARRAY_CONTAINS(tags, 'hadoop') AS has_hadoop, — 是否包含元素
    SORT_ARRAY(tags) AS sorted_tags, — 数组排序
    ARRAY_MIN(scores) AS min_score,
    ARRAY_MAX(scores) AS max_score,
    MAP_KEYS(props) AS prop_keys, — Map 的键列表
    MAP_VALUES(props) AS prop_values, — Map 的值列表
    STR_TO_MAP('a:1,b:2', ',', ':') AS prop_map — 字符串转 Map
    FROM complex_table;


    11. 用户自定义函数(UDF / UDAF / UDTF)

    11.1 三类自定义函数对比

    类型全称输入输出关系典型内置示例用途
    UDF User Defined Function 一行输入 → 一行输出(1:1) UPPER(), LENGTH() 字段转换、计算
    UDAF User Defined Aggregate Function 多行输入 → 一行输出(N:1) COUNT(), SUM() 自定义聚合计算
    UDTF User Defined Table-Generating Function 一行输入 → 多行输出(1:N) EXPLODE(), JSON_TUPLE() 行展开、数组拆分

    11.2 编写简单 UDF

    // 示例:将字符串中的手机号脱敏(替换中间4位为****)
    package com.example.hive.udf;

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

    @Description(
    name = "mask_phone",
    value = "_FUNC_(phone) – Masks the middle 4 digits of phone number",
    extended = "Example: SELECT mask_phone('13812345678') FROM dual;"
    )
    public class MaskPhoneUDF extends UDF {

    public Text evaluate(Text phone) {
    if (phone == null) return null;
    String phoneStr = phone.toString();
    if (phoneStr.length() != 11) return phone;
    return new Text(phoneStr.substring(0, 3) + "****" + phoneStr.substring(7));
    }

    // 方法重载:处理多种输入类型
    public String evaluate(String phone) {
    if (phone == null || phone.length() != 11) return phone;
    return phone.substring(0, 3) + "****" + phone.substring(7);
    }
    }

    # 编译打包(Maven 方式)
    mvn clean package -DskipTests
    # 生成 target/my-hive-udf.jar

    — 在 Hive 中注册并使用 UDF

    — 方式1:临时函数(当前会话有效)
    ADD JAR hdfs:///jars/my-hive-udf.jar;
    CREATE TEMPORARY FUNCTION mask_phone AS 'com.example.hive.udf.MaskPhoneUDF';

    — 方式2:永久函数(写入 Metastore,所有会话可用)
    — 需先将 JAR 上传到 HDFS
    CREATE FUNCTION mydb.mask_phone AS 'com.example.hive.udf.MaskPhoneUDF'
    USING JAR 'hdfs:///jars/my-hive-udf.jar';

    — 使用自定义函数
    SELECT user_id, mask_phone(phone) AS masked_phone FROM users;

    — 查看已注册函数
    SHOW FUNCTIONS LIKE 'mask*';
    DESCRIBE FUNCTION mask_phone;
    DESCRIBE FUNCTION EXTENDED mask_phone;

    — 删除函数
    DROP TEMPORARY FUNCTION mask_phone;
    DROP FUNCTION IF EXISTS mydb.mask_phone;

    11.3 编写 GenericUDF(支持复杂类型)

    // GenericUDF:支持数组、Map、Struct 等复杂类型
    package com.example.hive.udf;

    import org.apache.hadoop.hive.ql.exec.Description;
    import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
    import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
    import org.apache.hadoop.hive.ql.metadata.HiveException;
    import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
    import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
    import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
    import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;

    @Description(name = "to_upper", value = "_FUNC_(str) – converts string to uppercase")
    public class ToUpperGenericUDF extends GenericUDF {

    private StringObjectInspector stringOI;

    @Override
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {
    if (arguments.length != 1) {
    throw new UDFArgumentException("to_upper takes exactly one argument");
    }
    if (!(arguments[0] instanceof StringObjectInspector)) {
    throw new UDFArgumentTypeException(0, "to_upper argument must be a string");
    }
    this.stringOI = (StringObjectInspector) arguments[0];
    return PrimitiveObjectInspectorFactory.javaStringObjectInspector; // 返回类型
    }

    @Override
    public Object evaluate(DeferredObject[] arguments) throws HiveException {
    String input = stringOI.getPrimitiveJavaObject(arguments[0].get());
    if (input == null) return null;
    return input.toUpperCase();
    }

    @Override
    public String getDisplayString(String[] children) {
    return "to_upper(" + children[0] + ")";
    }
    }

    11.4 编写 UDAF

    // UDAF:统计字符串列中字符总长度
    package com.example.hive.udaf;

    import org.apache.hadoop.hive.ql.exec.UDAF;
    import org.apache.hadoop.hive.ql.exec.UDAFEvaluator;
    import org.apache.hadoop.io.LongWritable;
    import org.apache.hadoop.io.Text;

    public class TotalLengthUDAF extends UDAF {

    public static class TotalLengthEvaluator implements UDAFEvaluator {
    private long total = 0;

    @Override
    public void init() { total = 0; }

    // 处理每行输入
    public boolean iterate(Text input) {
    if (input != null) total += input.getLength();
    return true;
    }

    // 返回部分聚合结果(Map 端输出)
    public LongWritable terminatePartial() {
    return new LongWritable(total);
    }

    // 合并部分结果(Reduce 端合并)
    public boolean merge(LongWritable partial) {
    if (partial != null) total += partial.get();
    return true;
    }

    // 返回最终结果
    public LongWritable terminate() {
    return new LongWritable(total);
    }
    }
    }

    11.5 编写 UDTF

    // UDTF:将 CSV 字符串拆分为多行
    package com.example.hive.udtf;

    import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
    import org.apache.hadoop.hive.ql.metadata.HiveException;
    import org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
    import org.apache.hadoop.hive.serde2.objectinspector.*;
    import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
    import java.util.ArrayList;

    public class SplitToRowsUDTF extends GenericUDTF {

    private PrimitiveObjectInspector stringOI;

    @Override
    public StructObjectInspector initialize(ObjectInspector[] argOIs) throws UDFArgumentException {
    // 定义输出列
    List<String> fieldNames = new ArrayList<>();
    List<ObjectInspector> fieldOIs = new ArrayList<>();
    fieldNames.add("value");
    fieldOIs.add(PrimitiveObjectInspectorFactory.javaStringObjectInspector);
    this.stringOI = (PrimitiveObjectInspector) argOIs[0];
    return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldOIs);
    }

    @Override
    public void process(Object[] args) throws HiveException {
    String input = (String) stringOI.getPrimitiveJavaObject(args[0]);
    if (input != null) {
    String[] parts = input.split(",");
    for (String part : parts) {
    forward(new Object[]{part.trim()}); // 每个元素输出一行
    }
    }
    }

    @Override
    public void close() throws HiveException {}
    }

    — 使用 UDTF
    CREATE TEMPORARY FUNCTION split_to_rows AS 'com.example.hive.udtf.SplitToRowsUDTF'
    USING JAR 'hdfs:///jars/my-hive-udf.jar';

    — 直接使用
    SELECT split_to_rows(tag_str) AS tag FROM raw_data;

    — 配合 LATERAL VIEW 使用
    SELECT id, tag
    FROM raw_data
    LATERAL VIEW split_to_rows(tag_str) tmp AS tag;


    12. Hive 执行引擎

    12.1 三种执行引擎对比

    特性MapReduceApache TezApache Spark
    计算模型 Map + Reduce(两阶段) DAG(任意拓扑) DAG + 内存 RDD
    中间结果 写磁盘 HDFS 写磁盘(可内存缓冲) 内存(可 spill 磁盘)
    延迟 高(秒~分钟) 中(亚秒~秒) 低(亚秒)
    复杂查询 多个 MR job,效率低 一个 DAG,高效 极高效
    容错 Task 级重试 同 MR RDD 血缘重算
    成熟度 最高 高(Hive 推荐) 高
    Hive 推荐版本 Hive 1.x 默认 Hive 2.x+ 推荐 Hive on Spark

    12.2 切换执行引擎

    — 查看当前执行引擎
    SET hive.execution.engine;

    — 切换到 Tez(推荐,绝大多数生产环境)
    SET hive.execution.engine=tez;

    — 切换到 Spark
    SET hive.execution.engine=spark;

    — 切换回 MapReduce
    SET hive.execution.engine=mr;

    12.3 LLAP(Live Long and Process)

    LLAP 是 Hive 2.0 引入的交互式查询加速功能:

    传统模式:提交查询 → 启动 JVM → 加载数据 → 执行 → 销毁 JVM(每次都有冷启动开销)
    LLAP 模式:常驻的 Daemon 进程 → 缓存热数据(行列缓存) → 亚秒级响应

    LLAP 核心特性:

    • 持久化的 Daemon(避免 JVM 冷启动)
    • 行列缓存(将 ORC/Parquet 热数据块缓存在内存)
    • 细粒度资源弹性(可根据负载动态调整)
    • 支持并发查询

    — 启用 LLAP(需要先部署 LLAP Daemons)
    SET hive.llap.execution.mode = auto;

    — 在 hive-site.xml 中配置
    — hive.llap.daemon.memory.per.instance.mb=4096
    — hive.llap.daemon.vcpus.per.instance=4
    — hive.llap.io.enabled=true


    13. Hive 性能调优

    13.1 小文件合并

    Hive 中小文件是最常见的性能问题之一,大量小文件会严重拖慢 NameNode 和 MapReduce 任务:

    — 方式1:查询时合并小文件(Map-Only 任务)
    SET hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
    SET mapreduce.input.fileinputformat.split.minsize=134217728; — 128MB
    SET mapreduce.input.fileinputformat.split.maxsize=268435456; — 256MB

    — 方式2:输出时合并小文件
    SET hive.merge.mapfiles=true; — 合并 Map-Only 任务输出
    SET hive.merge.mapredfiles=true; — 合并 MapReduce 任务输出
    SET hive.merge.size.per.task=268435456; — 目标合并文件大小 256MB
    SET hive.merge.smallfiles.avgsize=134217728; — 触发合并的平均文件大小阈值

    — 方式3:定期手动合并(ORC 格式)
    ALTER TABLE user_events PARTITION (dt='2024-01-01') CONCATENATE;

    — 方式4:Spark 重写(最彻底的方式)
    INSERT OVERWRITE TABLE t PARTITION(dt='2024-01-01')
    SELECT * FROM t WHERE dt='2024-01-01';

    13.2 分区裁剪优化

    — ❌ 错误:分区条件在函数内,无法裁剪
    SELECT * FROM user_events WHERE YEAR(dt) = 2024 AND MONTH(dt) = 1;

    — ✅ 正确:直接在分区列上使用字符串比较
    SELECT * FROM user_events WHERE dt BETWEEN '2024-01-01' AND '2024-01-31';
    SELECT * FROM user_events WHERE dt >= '2024-01-01' AND dt < '2024-02-01';

    — 验证分区裁剪是否生效
    EXPLAIN SELECT * FROM user_events WHERE dt = '2024-01-01';
    — 在执行计划中查找 "partition filter"

    — 强制分区过滤(防止全表扫描)
    SET hive.mapred.mode=strict; — 查询分区表时必须有分区条件,否则报错

    13.3 MapJoin(小表 JOIN 优化)

    — 自动 MapJoin(Hive 自动判断小表)
    SET hive.auto.convert.join=true; — 默认 true
    SET hive.mapjoin.smalltable.filesize=25000000; — 小表阈值:25MB
    SET hive.auto.convert.join.noconditionaltask=true;
    SET hive.auto.convert.join.noconditionaltask.size=10000000; — 10MB

    — 手动指定 MapJoin(HINT 方式)
    SELECT /*+ MAPJOIN(d) */ e.name, d.dept_name
    FROM employees e JOIN departments d ON e.dept_id = d.id;

    — Bucket Map Join(两表按相同列分桶,且桶数相同)
    SET hive.optimize.bucketmapjoin=true;
    SET hive.optimize.bucketmapjoin.sortedmerge=true; — SMB Join(最高效)

    13.4 数据倾斜处理

    数据倾斜是导致 Hive 作业长时间卡在 99% 的最常见原因。

    — 1. 开启倾斜 Join 优化
    SET hive.optimize.skewjoin=true;
    SET hive.skewjoin.key=100000; — 超过 10 万行认为是热点 key

    — 2. 随机前缀法(解决 GROUP BY 热点 key)
    — 第一步:加随机前缀,拆散热点 key
    SELECT CONCAT(FLOOR(RAND() * 100), '_', user_id) AS rkey,
    SUM(amount) AS partial_sum
    FROM orders GROUP BY CONCAT(FLOOR(RAND() * 100), '_', user_id);

    — 第二步:去掉前缀,再次聚合
    SELECT SPLIT(rkey, '_')[1] AS user_id, SUM(partial_sum)
    FROM (上面的子查询) t GROUP BY SPLIT(rkey, '_')[1];

    — 3. 过滤 NULL Key(NULL JOIN 时会全部分到同一 Reducer)
    SELECT e.*, d.*
    FROM employees e
    JOIN departments d ON e.dept_id IS NOT NULL AND e.dept_id = d.id;

    — 4. 两阶段聚合(Map 端预聚合)
    SET hive.map.aggr=true; — 开启 Map 端聚合(默认开启)
    SET hive.groupby.skewindata=true; — 倾斜数据随机分发到 Reducer(两次 MR)

    13.5 Tez 引擎调优

    — Tez 容器大小(AM 和 Task 都用这个)
    SET tez.am.resource.memory.mb=1024;
    SET tez.task.resource.memory.mb=2048;
    SET tez.task.launch.cmd–opts=–Xmx1800m;

    — 关闭 Tez Session(按需启动,节省资源)
    SET tez.session.am.dag.submit.timeout.secs=600;

    — 开启预取优化
    SET tez.runtime.enable.final–merge.in.output=true;

    — 增加并行度
    SET hive.exec.parallel=true; — 允许并行执行多个 Stage
    SET hive.exec.parallel.thread.number=8; — 最大并行线程数

    13.6 CBO(基于代价的优化器)

    — 启用 CBO(需要先收集统计信息)
    SET hive.cbo.enable=true; — 默认 true(Hive 0.14+)
    SET hive.compute.query.using.stats=true;
    SET hive.stats.fetch.column.stats=true;
    SET hive.stats.fetch.partition.stats=true;

    — 收集统计信息(建议定期对重要表执行)
    ANALYZE TABLE employees COMPUTE STATISTICS; — 表级别统计
    ANALYZE TABLE employees COMPUTE STATISTICS FOR COLUMNS; — 列级别统计
    ANALYZE TABLE user_events PARTITION (dt='2024-01-01') COMPUTE STATISTICS;

    — 查看统计信息
    DESCRIBE FORMATTED employees; — 在输出中找 numRows、totalSize

    — 在 hive-site.xml 中启用自动统计收集
    — hive.stats.autogather=true (INSERT/LOAD 后自动更新)

    13.7 向量化执行

    — 开启向量化执行(一次处理 1024 行,利用 CPU SIMD 指令)
    SET hive.vectorized.execution.enabled=true; — 默认 true(Hive 0.13+)
    SET hive.vectorized.execution.reduce.enabled=true;
    SET hive.vectorized.execution.reduce.groupby.enabled=true;

    — 查看向量化是否生效
    EXPLAIN VECTORIZATION SELECT * FROM employees;

    13.8 常见性能配置汇总

    — 一次性优化配置(可放入 hive-site.xml 或每次 Session 开始时执行)
    SET hive.execution.engine=tez;
    SET hive.auto.convert.join=true;
    SET hive.cbo.enable=true;
    SET hive.compute.query.using.stats=true;
    SET hive.exec.parallel=true;
    SET hive.exec.parallel.thread.number=8;
    SET hive.vectorized.execution.enabled=true;
    SET hive.exec.dynamic.partition=true;
    SET hive.exec.dynamic.partition.mode=nonstrict;
    SET hive.merge.mapfiles=true;
    SET hive.merge.mapredfiles=true;
    SET hive.merge.size.per.task=256000000;
    SET hive.map.aggr=true;
    SET hive.groupby.skewindata=true;
    SET hive.exec.compress.intermediate=true;
    SET hive.exec.compress.output=true;


    14. Hive 分区管理深入

    14.1 静态分区 vs 动态分区

    对比项静态分区动态分区
    分区值 手动指定 查询时自动从数据中提取
    速度 快(无需扫描分区列) 较慢(需要额外 Reducer)
    使用场景 已知分区值,如按日期加载 分区值多或未知
    语法 PARTITION (dt='2024-01-01') PARTITION (dt)

    — 静态分区
    INSERT INTO TABLE user_events PARTITION (dt='2024-01-01', country='CN')
    SELECT user_id, event_type, event_time, page_url
    FROM raw_events_20240101;

    — 动态分区(分区列放在 SELECT 最后)
    SET hive.exec.dynamic.partition=true;
    SET hive.exec.dynamic.partition.mode=nonstrict;
    SET hive.exec.max.dynamic.partitions=1000; — 最大动态分区数
    SET hive.exec.max.dynamic.partitions.pernode=300; — 每节点最大动态分区数

    INSERT OVERWRITE TABLE user_events PARTITION (dt, country)
    SELECT user_id, event_type, event_time, page_url, dt, country — dt 和 country 在最后
    FROM raw_events;

    14.2 分区命名规范建议

    — 推荐:字符串分区键,格式一致
    PARTITIONED BY (dt STRING COMMENT 'date partition, format: yyyyMMdd')

    — 推荐:多级分区,粗粒度在前
    PARTITIONED BY (year STRING, month STRING, day STRING)

    — 注意:分区值本身不存储在数据文件中,只体现在目录名中
    — 不建议将高基数列(如 user_id)作为分区键,会产生大量小文件

    14.3 分区维护

    — 检查并修复分区(HDFS 目录存在但 Metastore 无记录)
    MSCK REPAIR TABLE user_events;

    — 检查分区完整性
    SHOW PARTITIONS user_events;

    — 查看特定分区的详情
    DESCRIBE FORMATTED user_events PARTITION (dt='2024-01-01');

    — 交换分区(在两张相同结构的表间快速移动分区数据)
    ALTER TABLE user_events EXCHANGE PARTITION (dt='2024-01-01') WITH TABLE user_events_staging;

    — 截断分区(仅清空数据,保留分区元数据)
    TRUNCATE TABLE user_events PARTITION (dt='2023-01-01');

    — 归档分区(压缩为 Hadoop Archive 文件,减少小文件数量)
    SET hive.archive.enabled=true;
    ALTER TABLE user_events ARCHIVE PARTITION (dt='2023-01-01');
    ALTER TABLE user_events UNARCHIVE PARTITION (dt='2023-01-01');


    15. Hive 元数据服务(Metastore)

    15.1 Metastore 三种部署模式

    嵌入式模式(Embedded)

    Hive CLI ─── Driver ─── Metastore API ─── Derby(嵌入式数据库)

    • Derby 数据库随 Hive 进程一起启动
    • 只支持单连接
    • 仅适合学习和测试
    本地模式(Local)

    Hive CLI ─── Driver ─── Metastore API ─── MySQL(同机)

    • Metastore 在 Hive 进程内运行,但使用外部 MySQL
    • 支持多连接,但每个 Hive 进程都直接连接数据库
    • 适合小型集群
    远程模式(Remote,生产推荐)

    Hive Client 1 ─┐
    Hive Client 2 ─┼─── Thrift Server ─── Metastore API ─── MySQL
    Spark/Impala ──┘ (9083 端口)

    • Metastore 作为独立服务运行
    • 所有客户端通过 Thrift 协议连接
    • 支持多客户端并发
    • 数据库连接由 Metastore 服务统一管理

    15.2 Metastore 重要配置

    <!– 元数据服务地址 –>
    <property>
    <name>hive.metastore.uris</name>
    <value>thrift://metastore-host:9083</value>
    </property>

    <!– 元数据库连接池配置 –>
    <property>
    <name>datanucleus.connectionPoolingType</name>
    <value>DBCP</value>
    </property>
    <property>
    <name>datanucleus.connectionPool.maxPoolSize</name>
    <value>20</value>
    </property>

    <!– 开启元数据缓存(减少 DB 查询) –>
    <property>
    <name>hive.metastore.cache.pinobjtypes</name>
    <value>Table,StorageDescriptor,SerDeInfo,Partition,Database,Type,FieldSchema,Order</value>
    </property>

    <!– Schema 版本兼容性检查 –>
    <property>
    <name>hive.metastore.schema.verification</name>
    <value>true</value>
    </property>

    15.3 Metastore HA(高可用)

    <!– 配置多个 Metastore 实例实现高可用 –>
    <property>
    <name>hive.metastore.uris</name>
    <value>thrift://metastore1:9083,thrift://metastore2:9083</value>
    </property>

    在多个节点上分别启动 Metastore 服务:

    hive –service metastore & # 在 metastore1 上
    hive –service metastore & # 在 metastore2 上


    16. HiveServer2 与 Beeline

    16.1 HiveServer2(HS2)

    HiveServer2 是 Hive 提供远程多并发客户端访问的服务:

    核心特性:

    • 多并发:支持多个客户端同时连接(HiveServer1 不支持)
    • 认证:Kerberos、LDAP、自定义认证
    • JDBC/ODBC 接口:标准 JDBC(端口 10000)
    • Web UI:默认 10002 端口,可监控 Sessions 和 Queries

    # 启动 HiveServer2
    hive –service hiveserver2 &
    # 或者(推荐,重定向日志)
    nohup $HIVE_HOME/bin/hiveserver2 > /var/log/hive/hiveserver2.log 2>&1 &

    # 查看 Web UI
    http://localhost:10002

    16.2 Beeline 使用详解

    Beeline 是基于 JDBC 的 HiveServer2 客户端,推荐替代旧的 Hive CLI:

    # 连接方式1:本地连接(不需要认证)
    beeline -u jdbc:hive2://localhost:10000

    # 连接方式2:指定用户名密码
    beeline -u jdbc:hive2://localhost:10000 -n hive -p password

    # 连接方式3:Kerberos 认证
    beeline -u "jdbc:hive2://localhost:10000/default;principal=hive/hostname@REALM"

    # 连接方式4:指定数据库
    beeline -u jdbc:hive2://localhost:10000/mydb

    # 非交互式:执行单个查询后退出
    beeline -u jdbc:hive2://localhost:10000 -e "SELECT COUNT(*) FROM employees"

    # 非交互式:执行 SQL 脚本文件
    beeline -u jdbc:hive2://localhost:10000 -f /path/to/script.hql

    # 关闭 beeline header 和 footer(适合脚本解析)
    beeline –silent=true –outputformat=tsv2 -u jdbc:hive2://localhost:10000 \\
    -e "SELECT * FROM employees" > output.tsv

    Beeline 交互式命令:

    — 连接到 HiveServer2
    !connect jdbc:hive2://localhost:10000

    — 断开连接
    !disconnect

    — 退出
    !quit

    — 查看所有命令
    !help

    — 查看当前连接信息
    !info

    — 执行 Shell 命令
    !sh ls /data/

    — 查看历史命令
    !history

    — 设置输出格式
    !set outputformat table — 表格(默认)
    !set outputformat csv2 — CSV
    !set outputformat tsv2 — TSV
    !set outputformat json — JSON

    — 显示/隐藏列 Header
    !set headerInterval 0 — 只显示一次 Header
    !set showHeader true/false

    — 设置最大行宽
    !set maxWidth 200
    !set maxColumnWidth 50

    16.3 JDBC 程序连接 Hive

    import java.sql.*;

    public class HiveJDBCExample {
    private static final String JDBC_URL = "jdbc:hive2://localhost:10000/default";
    private static final String DRIVER_CLASS = "org.apache.hive.jdbc.HiveDriver";

    public static void main(String[] args) throws Exception {
    Class.forName(DRIVER_CLASS);

    try (Connection conn = DriverManager.getConnection(JDBC_URL, "hive", "");
    Statement stmt = conn.createStatement()) {

    // 创建表
    stmt.execute("CREATE TABLE IF NOT EXISTS test_jdbc (id INT, name STRING) STORED AS ORC");

    // 插入数据
    stmt.execute("INSERT INTO test_jdbc VALUES (1, 'Alice'), (2, 'Bob')");

    // 查询
    try (ResultSet rs = stmt.executeQuery("SELECT * FROM test_jdbc")) {
    ResultSetMetaData metaData = rs.getMetaData();
    while (rs.next()) {
    for (int i = 1; i <= metaData.getColumnCount(); i++) {
    System.out.print(rs.getString(i) + "\\t");
    }
    System.out.println();
    }
    }
    }
    }
    }

    Maven 依赖:

    <dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-jdbc</artifactId>
    <version>3.1.3</version>
    </dependency>


    17. Hive 安全机制

    17.1 认证方式

    认证方式适用场景配置方式
    无认证 开发/测试 默认
    LDAP 企业 Active Directory 集成 hive.server2.authentication=LDAP
    Kerberos 企业生产安全环境 hive.server2.authentication=KERBEROS
    Custom 自定义认证插件 hive.server2.authentication=CUSTOM
    PAM Linux PAM 认证 hive.server2.authentication=PAM

    <!– Kerberos 认证配置示例 –>
    <property>
    <name>hive.server2.authentication</name>
    <value>KERBEROS</value>
    </property>
    <property>
    <name>hive.server2.kerberos.principal</name>
    <value>hive/_HOST@YOUR-REALM.COM</value>
    </property>
    <property>
    <name>hive.server2.kerberos.keytab</name>
    <value>/etc/security/keytabs/hive.service.keytab</value>
    </property>

    17.2 授权机制

    — Hive 内置权限控制(基于 SQL 标准)
    — 启用(hive-site.xml 中):
    — hive.security.authorization.enabled=true
    — hive.security.authorization.manager=org.apache.hadoop.hive.ql.security.authorization.plugin.sqlstd.SQLStdHiveAuthorizerFactory

    — 创建角色
    CREATE ROLE analyst;
    CREATE ROLE data_engineer;

    — 授予角色权限
    GRANT SELECT ON DATABASE sales_db TO ROLE analyst;
    GRANT ALL ON TABLE employees TO ROLE data_engineer;
    GRANT SELECT ON TABLE employees (name, dept) TO ROLE analyst; — 列级权限

    — 将角色赋予用户
    GRANT ROLE analyst TO USER alice;
    GRANT ROLE data_engineer TO USER bob;

    — 撤销权限
    REVOKE SELECT ON DATABASE sales_db FROM ROLE analyst;
    REVOKE ROLE analyst FROM USER alice;

    — 查看权限
    SHOW GRANT USER alice ON TABLE employees;
    SHOW ROLE GRANT USER alice;
    SHOW GRANTS ON TABLE employees;

    — 删除角色
    DROP ROLE analyst;

    17.3 与 Apache Ranger 集成

    Apache Ranger 提供企业级细粒度权限控制:

    用户请求 → HiveServer2 → Ranger 插件鉴权 → 允许/拒绝
    ↑
    Ranger Admin(策略管理中心)
    ↑
    Ranger Audit(审计日志)

    Ranger 支持:

    • 数据库/表/列/行级别权限控制
    • 基于用户/组/角色的权限策略
    • 数据掩码(敏感数据自动脱敏)
    • 行过滤(不同用户看到不同行)
    • 完整的审计日志

    18. Hive 与生态系统集成

    18.1 Hive on Spark

    # 在 hive-site.xml 中配置
    # hive.execution.engine=spark
    # spark.master=yarn
    # spark.submit.deployMode=cluster

    — 切换到 Spark 引擎
    SET hive.execution.engine=spark;

    — Spark 相关配置
    SET spark.executor.memory=4g;
    SET spark.executor.cores=2;
    SET spark.executor.instances=10;
    SET spark.dynamicAllocation.enabled=true;

    — 执行查询(透明使用 Spark 计算)
    SELECT dept, AVG(salary) FROM employees GROUP BY dept;

    18.2 与 Spark SQL 共享 Metastore

    Spark SQL 和 Hive 可以共享同一个 Metastore,让两个系统看到相同的表结构:

    // Spark 代码中配置 Hive Metastore
    val spark = SparkSession.builder()
    .appName("HiveIntegration")
    .config("spark.sql.warehouse.dir", "/user/hive/warehouse")
    .config("hive.metastore.uris", "thrift://localhost:9083")
    .enableHiveSupport()
    .getOrCreate()

    // 直接查询 Hive 表
    spark.sql("SELECT * FROM sales_db.orders LIMIT 10").show()

    // Spark 写入的表在 Hive 中可见
    spark.sql("""
    CREATE TABLE IF NOT EXISTS spark_result
    USING ORC
    AS SELECT dept, SUM(salary) FROM employees GROUP BY dept
    """
    )

    18.3 与 HBase 集成

    — 创建 Hive-HBase 映射表(通过 HBase StorageHandler)
    CREATE TABLE hbase_users (
    key STRING,
    name STRING,
    age INT,
    email STRING
    )
    STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
    WITH SERDEPROPERTIES (
    'hbase.columns.mapping' = ':key,info:name,info:age,info:email'
    )
    TBLPROPERTIES ('hbase.table.name' = 'users');

    — 通过 Hive 查询 HBase 数据
    SELECT * FROM hbase_users WHERE key = 'user001';

    18.4 与 Apache Iceberg 集成(Hive 4.x)

    Apache Iceberg 是新一代开放表格式,Hive 4.x 对其提供原生支持:

    — 创建 Iceberg 表
    CREATE TABLE iceberg_orders (
    order_id BIGINT,
    user_id INT,
    amount DECIMAL(10,2),
    status STRING,
    create_ts TIMESTAMP
    )
    STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'
    LOCATION '/warehouse/iceberg/orders'
    TBLPROPERTIES (
    'table_type'='ICEBERG',
    'format-version'='2', — Iceberg v2(支持 Row-level Updates)
    'write.delete.mode'='merge-on-read' — 删除模式
    );

    — Iceberg 支持的时间旅行(Time Travel)
    — 查询历史快照
    SELECT * FROM iceberg_orders FOR SYSTEM_TIME AS OF '2024-01-01 00:00:00';
    SELECT * FROM iceberg_orders FOR SYSTEM_VERSION AS OF 12345678;

    — 查看表历史
    SELECT * FROM iceberg_orders.history;
    SELECT * FROM iceberg_orders.snapshots;

    — Iceberg Z-order 排序(Hive 4.x 新特性)
    ALTER TABLE iceberg_orders EXECUTE OPTIMIZE(ZORDER BY (user_id, create_ts));

    18.5 与 Sqoop 集成

    # Sqoop 从 MySQL 导入数据到 Hive 表
    sqoop import \\
    –connect jdbc:mysql://mysql-host:3306/sales \\
    –username root –password secret \\
    –table orders \\
    –hive-import \\
    –hive-database sales_db \\
    –hive-table orders_from_mysql \\
    –hive-overwrite \\
    –num-mappers 4

    # Sqoop 将 Hive 表数据导出到 MySQL
    sqoop export \\
    –connect jdbc:mysql://mysql-host:3306/sales \\
    –username root –password secret \\
    –table mysql_target \\
    –hcatalog-database sales_db \\
    –hcatalog-table hive_source


    19. Hive 4.x 新特性

    19.1 Iceberg v3 深度集成

    — 支持 Iceberg v3 功能:Deletion Vectors(删除向量)
    — 比 MoR 模式更高效的行级删除实现
    CREATE TABLE orders_v3 (...)
    STORED BY 'org.apache.iceberg.mr.hive.HiveIcebergStorageHandler'
    TBLPROPERTIES (
    'format-version'='3',
    'write.delete.mode'='merge-on-read'
    );

    — Z-ordering 优化(空间近邻填充曲线,提升多列过滤性能)
    ALTER TABLE orders_v3 EXECUTE OPTIMIZE(ZORDER BY (user_id, date));

    — Variant 类型(半结构化数据,类似 JSON Schema)
    CREATE TABLE semi_struct (id BIGINT, data VARIANT);

    19.2 JDK 21 支持

    Hive 4.x 支持 Java 21,可使用虚拟线程(Virtual Threads)提升 HS2 并发性能。

    19.3 HMS REST Catalog

    — Hive Metastore 暴露 REST API,兼容 Apache Iceberg REST Catalog 协议
    — 允许 Spark、Flink 通过标准 REST API 访问 Hive 元数据

    19.4 内置自动 Compaction

    Hive 4.x 加入了 ACID 表的自动 Compaction 功能,无需手动触发:

    — 查看 compaction 队列
    SHOW COMPACTIONS;

    — 手动触发 compaction(Major:合并所有增量到基础文件)
    ALTER TABLE student COMPACT 'major';

    — 手动触发 Minor compaction(合并增量文件)
    ALTER TABLE student COMPACT 'minor';


    20. 常见问题与排查

    20.1 Hive 查询卡住不动

    排查步骤:

    # 1. 查看 YARN 作业状态
    yarn application -list
    yarn application -status <application_id>

    # 2. 查看 Hive 日志
    tail -f $HIVE_HOME/logs/hive.log

    # 3. 查看 YARN 作业日志
    yarn logs -applicationId application_XXXXX

    # 4. 检查是否有 Reducer 数据倾斜(YARN UI http://master:8088 中查看各 Reducer 进度)

    20.2 “Too many dynamic partitions” 错误

    — 错误信息:Number of dynamic partitions created is 2000, which is more than 1000
    — 解决:增大动态分区限制
    SET hive.exec.max.dynamic.partitions=5000;
    SET hive.exec.max.dynamic.partitions.pernode=1000;

    20.3 Out of Memory 错误

    — 增大 Map/Reduce 内存
    SET mapreduce.map.memory.mb=4096;
    SET mapreduce.reduce.memory.mb=8192;
    SET mapreduce.map.java.opts=–Xmx3276m;
    SET mapreduce.reduce.java.opts=–Xmx6553m;

    — 增大 Tez 容器大小
    SET tez.task.resource.memory.mb=4096;
    SET tez.task.launch.cmd–opts=–Xmx3276m;

    20.4 Metastore 连接失败

    # 检查 Metastore 服务是否运行
    netstat -tuln | grep 9083
    # 或
    ps aux | grep HiveMetaStore

    # 重启 Metastore
    pkill -f HiveMetaStore
    nohup hive –service metastore > /tmp/metastore.log 2>&1 &

    # 检查 MySQL 连接
    mysql -h localhost -u hive -p metastore

    # 检查 schema 版本
    schematool -dbType mysql -info

    20.5 “Unable to move source” 错误

    # 原因:HDFS 临时目录权限问题
    hdfs dfs -chmod 777 /tmp/hive
    hdfs dfs -chown -R hive:hdfs /user/hive/warehouse

    # 在 hive-site.xml 中设置 hive 临时目录
    # hive.exec.scratchdir=/tmp/hive
    # hive.downloaded.resources.dir=/tmp/hive/resources

    20.6 全表扫描警告

    — 错误:Strict mode requires that a partition filter is present before returning from this call
    — 原因:hive.mapred.mode=strict 时,查询分区表必须有分区条件

    — 解决方案1:添加分区条件
    SELECT * FROM user_events WHERE dt = '2024-01-01';

    — 解决方案2:临时关闭 strict 模式
    SET hive.mapred.mode=nonstrict;

    20.7 Join 内存溢出(小表 MapJoin 失败)

    — 增大 MapJoin 阈值
    SET hive.mapjoin.smalltable.filesize=128000000; — 128MB
    SET hive.auto.convert.join.noconditionaltask.size=128000000;

    — 或关闭自动 MapJoin,改用普通 Join
    SET hive.auto.convert.join=false;


    21. 最佳实践总结

    21.1 建表规范

    — ✅ 推荐建表模式
    CREATE TABLE sales_order (
    order_id BIGINT COMMENT '订单ID(主键)',
    user_id INT COMMENT '用户ID',
    product_id INT COMMENT '商品ID',
    amount DECIMAL(12,2) COMMENT '订单金额',
    create_ts TIMESTAMP COMMENT '下单时间'
    )
    COMMENT '销售订单明细表'
    PARTITIONED BY (dt STRING COMMENT '日期分区 yyyyMMdd')
    STORED AS ORC
    TBLPROPERTIES (
    'orc.compress'='SNAPPY',
    'author'='data_eng_team',
    'create_time'='2024-01-01'
    );

    21.2 数据导入规范

    # 1. 批量数据:使用 LOAD DATA 或 INSERT OVERWRITE
    # 2. 增量数据:INSERT INTO(追加)
    # 3. 大批量 ETL:INSERT OVERWRITE TABLE … SELECT …(效率最高)
    # 4. 导入后运行 ANALYZE TABLE 收集统计信息

    21.3 查询优化清单

    □ 分区表查询必须包含分区条件
    □ 优先使用 ORC 或 Parquet 格式
    □ 小表 JOIN 使用 MAPJOIN hint
    □ 避免 SELECT *,只查需要的列
    □ GROUP BY 使用高基数列(低基数考虑分桶后 SMB Join)
    □ 使用 EXPLAIN 分析执行计划
    □ 对核心表执行 ANALYZE TABLE 收集统计信息
    □ 避免在 WHERE 条件中对分区列使用函数
    □ 大查询优先使用 Tez 引擎
    □ 数据倾斜时使用 hive.groupby.skewindata=true

    21.4 EXPLAIN 使用

    — 查看执行计划
    EXPLAIN SELECT dept, COUNT(*) FROM employees WHERE salary > 10000 GROUP BY dept;

    — 查看详细执行计划(含操作符树)
    EXPLAIN EXTENDED SELECT ...;

    — 查看依赖关系
    EXPLAIN DEPENDENCY SELECT ...;

    — 查看向量化信息
    EXPLAIN VECTORIZATION SELECT ...;

    — 查看 CBO 相关信息(需 SET hive.cbo.enable=true)
    EXPLAIN ANALYZE SELECT ...;

    21.5 Hive 命令行技巧

    # 执行单个 HQL 后退出
    hive -e "SELECT COUNT(*) FROM employees"

    # 执行 HQL 脚本文件
    hive -f /data/scripts/report.hql

    # 传递变量到 HQL 脚本(使用 hiveconf)
    hive -f report.hql –hiveconf dt=2024-01-01
    # 在 HQL 中使用:WHERE dt = '${hiveconf:dt}'

    # 静默模式(去掉 INFO 日志)
    hive -S -e "SELECT …"

    # 初始化 HQL(每次启动时执行)
    hive –hiveconf hive.session.id=mysession -i /data/scripts/init.hql -f report.hql


    22. Hive 与其他技术对比

    22.1 Hive vs Spark SQL

    对比维度Hive(+Tez)Spark SQL
    擅长场景 超大批量 ETL,PB 级离线处理 复杂分析,迭代计算,ML 管道
    查询延迟 秒~分钟级 亚秒~秒级
    内存使用 磁盘为主,内存需求低 内存密集型
    SQL 兼容 HiveQL(HQL),自己的方言 ANSI SQL,兼容 HiveQL
    生态整合 Hadoop 原生,Metastore 标准 支持 Hive Metastore
    小文件处理 需要手动合并 自动处理能力强
    流批一体 仅批处理 批处理 + Structured Streaming

    22.2 Hive vs Presto/Trino

    对比维度HivePresto/Trino
    定位 批处理 ETL 工具 交互式 OLAP 查询引擎
    延迟 高(秒~分钟) 低(毫秒~秒,MPP 并行)
    数据源 HDFS/S3/HBase 多源联邦:Hive/MySQL/S3/Kafka 等
    大数据集 擅长(PB 级 ETL) 内存有限,超大结果集可能 OOM
    SQL 支持 HiveQL 扩展 接近标准 ANSI SQL
    使用场景 数据入库、转换、批量报表 BI 即席查询、实时大屏

    22.3 Hive vs Impala

    对比维度HiveImpala
    架构 MapReduce/Tez/Spark 执行 原生 MPP,C++ 实现
    延迟 高 低(内存 MPP,毫秒级)
    容错 强(MR/Tez 容错机制) 弱(查询失败需重试)
    UDF Java/Python Java(有限)
    共享 Metastore 是(HMS) 是(共享 Hive HMS)
    适用场景 大批量 ETL 快速分析查询

    22.4 2024 年 Hive 的定位

    Hive 在现代数据栈中的核心价值仍然存在:

    数据湖架构中的 Hive 角色(2024):

    存储层: HDFS / S3 / OSS(对象存储)
    表格式: Hive 表 / Apache Iceberg / Apache Hudi / Apache Delta Lake
    批处理: Hive(ETL)/ Spark(复杂计算)
    即席查询:Presto / Trino / Spark SQL
    元数据: Hive Metastore(HMS,事实上的行业标准)

    HMS(Hive Metastore Service)已成为大数据生态的元数据中枢,即使不使用 Hive 做查询,Spark、Presto、Flink 等都依赖 HMS 管理表元数据。这是 Hive 在现代架构中最核心的价值所在。


    23. 附录:配置项速查 & 官方资源

    23.1 重要配置项汇总

    配置项默认值说明
    hive.execution.engine mr 执行引擎:mr/tez/spark
    hive.metastore.warehouse.dir /user/hive/warehouse Hive 仓库目录
    hive.exec.dynamic.partition false 是否启用动态分区
    hive.exec.dynamic.partition.mode strict 动态分区模式:strict/nonstrict
    hive.exec.max.dynamic.partitions 1000 最大动态分区数
    hive.auto.convert.join true 自动转换 MapJoin
    hive.mapjoin.smalltable.filesize 25MB MapJoin 小表阈值
    hive.cbo.enable true 启用 CBO 优化器
    hive.vectorized.execution.enabled true 启用向量化执行
    hive.exec.parallel false 并行执行多个 Stage
    hive.merge.mapfiles true 合并 Map-only 输出小文件
    hive.merge.mapredfiles false 合并 MR 输出小文件
    hive.groupby.skewindata false 数据倾斜时随机分发
    hive.map.aggr true Map 端预聚合
    hive.mapred.mode nonstrict strict 模式强制分区条件
    hive.optimize.skewjoin false 倾斜 Join 优化
    hive.server2.thrift.port 10000 HiveServer2 端口
    hive.metastore.port 9083 Metastore Thrift 端口
    hive.server2.webui.port 10002 HiveServer2 Web UI 端口

    23.2 默认端口速查

    服务端口协议
    Hive Metastore 9083 Thrift
    HiveServer2(JDBC/ODBC) 10000 Thrift/HTTP
    HiveServer2 Web UI 10002 HTTP
    Hive CLI(本地) – 本地进程

    23.3 官方资源链接

    资源URL
    Apache Hive 官网 https://hive.apache.org/
    官方 Wiki 文档 https://cwiki.apache.org/confluence/display/Hive/Home
    Hive 下载页面 https://hive.apache.org/downloads.html
    快速开始指南 https://hive.apache.org/development/quickstart/
    语言手册(DDL) https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL
    语言手册(DML) https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DML
    语言手册(UDF) https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
    设计文档 https://hive.apache.org/development/desingdocs/design/
    管理员手册 https://hive.apache.org/docs/latest/admin/
    HiveServer2 文档 https://cwiki.apache.org/confluence/display/Hive/Setting+Up+HiveServer2
    Hive GitHub https://github.com/apache/hive

    23.4 常用 SQL 速查

    — 查看当前配置
    SET hive.execution.engine; — 查看单个配置
    SET; — 查看所有配置

    — 查看当前数据库
    SELECT current_database();

    — 查看 Hive 版本
    SELECT version();

    — 查看函数列表
    SHOW FUNCTIONS;
    SHOW FUNCTIONS LIKE 'str*';

    — 查看建表语句
    SHOW CREATE TABLE table_name;

    — 查看分区列表
    SHOW PARTITIONS table_name;

    — 查看锁
    SHOW LOCKS table_name;

    — 释放锁
    UNLOCK TABLE table_name;

    — 查看正在运行的查询(HS2 Web UI)
    — http://localhost:10002/queries

    — 执行计划
    EXPLAIN [EXTENDED|VECTORIZATION|DEPENDENCY|AUTHORIZATION|ANALYZE] query;

    赞(0)
    未经允许不得转载:171主机测评 » Hive大数据实战指南:从入门到精通
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址