Hive SQL 使用及进阶详解

一、Hive 简介

Hive 是建立在 Hadoop 之上的数据仓库基础架构,它提供了类似于 SQL 的查询语言 Hive SQL(也称为 HQL),用于对存储在 Hadoop 分布式文件系统(HDFS)中的大规模数据进行数据查询和分析。Hive 将 SQL 查询转换为 MapReduce、Tez 或 Spark 等分布式计算任务,使得不熟悉 Java 编程的数据分析人员也能方便地处理大规模数据。

二、Hive SQL 基础使用

(一)环境准备

在使用 Hive SQL 之前,需要确保 Hadoop 集群和 Hive 已经正确安装和配置。启动 Hadoop 服务(如 HDFS、YARN)后,启动 Hive 服务。通常可以通过以下命令启动 Hive 客户端:

bash

hive

(二)数据库操作

1. 创建数据库

sql

CREATE DATABASE IF NOT EXISTS my_database;

IF NOT EXISTS 是可选的,用于避免在数据库已经存在时抛出错误。

2. 使用数据库

sql

USE my_database;
3. 查看数据库

sql

SHOW DATABASES;
4. 删除数据库

sql

DROP DATABASE IF EXISTS my_database;

如果数据库中有表,需要使用 CASCADE 关键字强制删除:

sql

DROP DATABASE IF EXISTS my_database CASCADE;

(三)表操作

1. 创建表

  • 内部表(管理表)

sql

CREATE TABLE IF NOT EXISTS employees (
    id INT,
    name STRING,
    age INT,
    salary DOUBLE
) ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
STORED AS TEXTFILE;

这里创建了一个名为 employees 的内部表,字段之间用逗号分隔,数据以文本文件形式存储。

  • 外部表

sql

CREATE EXTERNAL TABLE IF NOT EXISTS external_employees (
    id INT,
    name STRING,
    age INT,
    salary DOUBLE
) ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LOCATION '/user/hive/external_data';

外部表使用 EXTERNAL 关键字,数据存储在指定的 LOCATION 目录下,删除外部表时不会删除数据文件。

2. 查看表

sql

SHOW TABLES;
3. 查看表结构

sql

DESCRIBE employees;
4. 删除表

sql

DROP TABLE IF EXISTS employees;

(四)数据操作

1. 加载数据

  • 从本地文件系统加载数据到内部表

sql

LOAD DATA LOCAL INPATH '/path/to/local/data.csv' INTO TABLE employees;

  • 从 HDFS 加载数据到内部表

sql

LOAD DATA INPATH '/user/hdfs/data.csv' INTO TABLE employees;
2. 插入数据

sql

INSERT INTO TABLE employees VALUES (1, 'John', 30, 5000.0);
3. 查询数据

sql

SELECT * FROM employees;

可以使用 WHERE 子句进行条件查询:

sql

SELECT * FROM employees WHERE age > 25;
4. 更新和删除数据

Hive 不支持直接的 UPDATE 和 DELETE 操作,通常可以通过创建新表并插入符合条件的数据来实现类似功能。例如,删除 age 小于 20 的记录:

sql

CREATE TABLE new_employees AS
SELECT * FROM employees WHERE age >= 20;

三、Hive SQL 进阶使用

(一)复杂查询

1. 连接查询

  • 内连接

sql

SELECT e.id, e.name, d.dept_name
FROM employees e
JOIN departments d
ON e.dept_id = d.dept_id;

  • 左外连接

sql

SELECT e.id, e.name, d.dept_name
FROM employees e
LEFT JOIN departments d
ON e.dept_id = d.dept_id;
2. 分组查询

sql

SELECT dept_id, AVG(salary)
FROM employees
GROUP BY dept_id;

可以使用 HAVING 子句对分组结果进行过滤:

sql

SELECT dept_id, AVG(salary)
FROM employees
GROUP BY dept_id
HAVING AVG(salary) > 5000;
3. 子查询

sql

SELECT *
FROM employees
WHERE dept_id IN (SELECT dept_id FROM departments WHERE dept_name = 'Sales');

(二)函数使用

1. 内置函数

  • 字符串函数:如 UPPERLOWERSUBSTRING 等。

sql

SELECT UPPER(name) FROM employees;

  • 数学函数:如 SUMAVGCOUNT 等。

sql

SELECT SUM(salary) FROM employees;

  • 日期函数:如 YEARMONTHDAY 等。

sql

SELECT YEAR(hire_date) FROM employees;
2. 自定义函数(UDF)

可以编写自定义函数来满足特定的业务需求。以下是一个简单的 Java 自定义函数示例:

java

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

public class MyUDF extends UDF {
    public Text evaluate(Text input) {
        if (input == null) return null;
        return new Text(input.toString().toUpperCase());
    }
}

将上述代码编译打包成 JAR 文件,然后在 Hive 中注册并使用:

sql

ADD JAR /path/to/myudf.jar;
CREATE TEMPORARY FUNCTION my_udf AS 'com.example.MyUDF';
SELECT my_udf(name) FROM employees;

(三)分区表和分桶表

1. 分区表

分区表可以根据指定的列(如日期、地区等)对数据进行分区,提高查询效率。

sql

CREATE TABLE partitioned_employees (
    id INT,
    name STRING,
    age INT,
    salary DOUBLE
) PARTITIONED BY (dept_id INT)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';

加载数据到指定分区:

sql

LOAD DATA INPATH '/user/hdfs/dept1_data.csv' INTO TABLE partitioned_employees PARTITION (dept_id = 1);
2. 分桶表

分桶表将数据按照指定列的哈希值进行分桶存储,常用于提高数据抽样和连接操作的效率。

sql

CREATE TABLE bucketed_employees (
    id INT,
    name STRING,
    age INT,
    salary DOUBLE
) CLUSTERED BY (id) INTO 4 BUCKETS
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';

(四)窗口函数

窗口函数用于在查询结果的特定窗口内进行计算,常见的窗口函数有 ROW_NUMBER()RANK()DENSE_RANK() 等。

sql

SELECT id, name, salary,
       ROW_NUMBER() OVER (ORDER BY salary DESC) as rank
FROM employees;

四、性能优化

(一)数据倾斜处理

  • 使用 DISTRIBUTE BY 和 SORT BY:在数据插入或查询时,合理使用 DISTRIBUTE BY 和 SORT BY 可以避免数据倾斜。

sql

INSERT OVERWRITE TABLE bucketed_employees
DISTRIBUTE BY id
SORT BY id;

  • 使用随机前缀:在进行分组聚合时,如果某些键的数据量过大,可以在键前添加随机前缀进行预处理。

(二)合理使用分区和分桶

根据数据的特点和查询需求,合理设计分区表和分桶表,减少不必要的数据扫描。

(三)优化查询语句

  • 避免使用 SELECT *,只选择需要的列。
  • 合理使用 JOIN 顺序,将小表放在前面。
  • 尽量使用 EXISTS 代替 IN 子查询。

(四)调整 Hive 参数

根据集群资源和数据量,调整 Hive 的相关参数,如 hive.auto.convert.joinmapred.reduce.tasks 等。

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