你的第一个 Hive 查询

大数据Beginner
立即练习

介绍

想象把零售商的订单记录作为电子表格打开。每行描述一个订单,每列描述一个属性,例如日期或付款状态。你想回答一个简单问题:团队应该先审核哪些已付款订单? 随着文件增大,逐行手动阅读就不方便了。

Apache Hive 让你将文件数据描述为表,并使用 SQL(结构化查询语言,Structured Query Language)提问。表定义描述列以及底层文件的位置;文件则保存实际记录。Hive 使用这个定义解释数据并执行查询。在预配置环境中,HDFS 提供存储,Hive 提供表和查询层。仅仅上传文件,并不会自动让它成为 Hive 表。

Hive 适用于对已存储数据进行分析查询,例如批量报表。它与编辑电子表格单元格不同,本课程也不把它当作每个应用的事务数据库替代品。这里先使用六条易读记录,让你在处理更大输入之前能够预测正确答案。

你将使用 Hive 的终端客户端 Beeline,连接正在运行的 HiveServer2 服务。服务和示例表已经准备好。你无需安装软件、初始化元数据,也无需预先了解 Java、Python、Hadoop 或 SQL。基本终端操作和读懂表格的能力就够了。需要更多终端或数据库练习时,可查看 Linux 和 Database 学习路径。

学习流程是:查看真实数据行,了解表结构,保存选择已付款订单的查询,再修改一个条件检验理解。

查看你的第一批 Hive 数据行

在这一步中,你将连接 Hive 并读取预置表,然后再学习如何缩小查询范围。

使用终端标签页。用 cd 进入本地项目目录:

cd /home/labex/project

Beeline 是客户端:它将 SQL 发送给 HiveServer2,由后者处理查询。在下面命令中,-u 提供连接 URL,-n 提供会话用户名,-e 提供需要执行的 SQL,执行后返回终端。所提供的 URL 连接当前机器上端口为 10000 的 Hive 服务,初始数据库为 default。这个教学服务不需要外部账号或密码。

SQL SELECT * FROM retail_intro.orders; 请求读取 retail_intro 数据库中 orders 表的所有列(*)。分号结束语句。单引号让整条 SQL 语句作为一个 Shell 参数传入:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'SELECT * FROM retail_intro.orders;'

查找六条订单行,以及 order_id、quantity、order_status 等列名。结果周围可能有连接消息和表格边框。找到订单 o1:数量为 2,单价为 10.00,状态为 paid(已付款)。订单 o3 为 pending(待付款),o5 为 refunded(已退款)。每行是一个只含一种商品类型的简化订单。

查询用于获取数据;这条 SELECT 不会改变付款状态,也不会更新源文件。没有排序子句时,不要假设 SQL 保证特定的行顺序。

将同一个查询的输出保存为本地记录。Shell 的 > 运算符会创建文件,或替换文件原有内容:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'SELECT * FROM retail_intro.orders;' > /home/labex/project/output/first-look.txt

在本地读取它:

cat /home/labex/project/output/first-look.txt

订单行应该仍然存在。终端运行了 Beeline 客户端,Hive 读取表定义和文件,Shell 将显示的结果保存到本地。接下来,你将探索查询背后的对象。

探索数据库、表和列

在这一步中,你将探索数据库和表定义,而不是猜测列名。

数据库(database)是将表分组的命名空间。SHOW DATABASES 列出可用数据库,不会读取它们的所有数据文件:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'SHOW DATABASES;'

找到 default 和 retail_intro。使用 USE 选择数据库,并在同一次调用中接着执行 SHOW TABLES:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'USE retail_intro; SHOW TABLES;'

应该找到 orders。每条 -e 命令都会打开新 Beeline 会话,因此某次调用中的 USE 不会自动延续到下一次。要么在每个 SQL 文件中选择数据库,要么使用限定名称 retail_intro.orders。

DESCRIBE 列出表的列和类型。例如,STRING 保存文本,INT 保存整数,DECIMAL(10,2) 保存有两位小数的定点数,DATE 表示日历日期:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex -e 'DESCRIBE retail_intro.orders;'

将字段与首次查询的行对应起来。数量和价格虽然看起来都是数字,但含义和类型不同。后面的实验会计算金额;今天只读取所提供的字段。

保存查询结果时,Beeline 可以使用简单文本格式。--outputformat=tsv2 选择制表符分隔字段,--showHeader=false 省略表头行,--silent=true 减少客户端附加消息。使用这些输出选项保存描述的模式(schema):

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -e 'DESCRIBE retail_intro.orders;' > /home/labex/project/output/table-schema.txt

记录中也可能包含运行时消息。重要的是模式行列出全部七列及其类型。表定义属于元数据:它告诉 Hive 如何解释已存储文件。下个实验将带你亲自建立这种映射。

保存查询以选出最前面的已付款订单

在这一步中,你将只选择审核团队所需的列和已付款行,并让结果顺序可预测。

查询可以通过几个互相独立的方式缩小数据范围:

子句 在这里的用途
SELECT 选择输出列
FROM 选择源表
WHERE 保留条件为真的行
ORDER BY 明确对结果排序
LIMIT 返回不超过指定数量的行

你将请求 order_id、order_status 和 quantity,只保留 paid 行,按订单 ID 排序,并返回前两行。预测哪些行会保留:在提供的六个订单中,o1 和 o2 是按此顺序排列的前两个已付款 ID。

将 SQL 保存在本地文件中,以便检查和重新运行。下一条 Shell 命令中的 cat > file <<'SQL' 开始一个 here-document(此处文档):直到结尾 SQL 之前的各行都会原样写入文件。它们是 SQL 文本,不是 Shell 命令。请复制完整代码块,包括分隔符行:

cat > /home/labex/project/queries/first-query.sql <<'SQL'
USE retail_intro;
SELECT order_id, order_status, quantity
FROM orders
WHERE order_status = 'paid'
ORDER BY order_id
LIMIT 2;
SQL

SQL 内带引号的 'paid' 是文本值。= 比较每行状态与该值是否相同,不会赋予新状态。USE 语句让文件独立于之前的客户端会话。

Beeline 的 -f 选项读取本地 SQL 文件。执行你的文件,并使用刚学过的文本格式选项保存输出:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/first-query.sql > /home/labex/project/output/first-query.txt

读取保存的记录:

cat /home/labex/project/output/first-query.txt

结果行应该为:

o1 paid 2
o2 paid 1

周围的运行时消息并不是订单记录。LIMIT 2 不意味着随意选两行:明确的排序决定了哪些匹配行排在最前面。现在你有了一个可复用查询文件,以及针对团队问题的可观察结果。

预测一个条件变化的影响

在这一步中,你将只修改状态条件,并检查返回行是否符合预测。

保留已付款订单查询不变。同一张表中有一个 pending 订单:o3,数量为 1。如果状态条件从 paid 改为 pending,限制为两行时应该返回多少行?限制是最大值,因此答案是一行。

编写相同查询,只修改这个条件:

cat > /home/labex/project/queries/pending-query.sql <<'SQL'
USE retail_intro;
SELECT order_id, order_status, quantity
FROM orders
WHERE order_status = 'pending'
ORDER BY order_id
LIMIT 2;
SQL

独立执行它:

beeline -u 'jdbc:hive2://localhost:10000/default' -n labex --silent=true --showHeader=false --outputformat=tsv2 -f /home/labex/project/queries/pending-query.sql > /home/labex/project/output/pending-query.txt

读取保存的结果:

cat /home/labex/project/output/pending-query.txt

唯一的订单行应该是:

o3 pending 1

修改筛选条件选择了不同的行,没有改变表中存储的记录。你已使用相同的基本查询结构回答两个问题。接下来,你将把现有 CSV 文件连接到表定义,而不再依赖预置表。

总结

你将 Hive 放入文件到表、再到查询的流程中,使用 Beeline 连接,并探索了数据库、表和模式。你编写了可复用 SQL 文件,运用了选列、筛选、明确排序和行数限制,再预测并核对了一个条件变化。

第一次体验使用了预置表。下个实验中,你将把 CSV 文件映射到自己的外部表,学习元数据与底层文件的关系。