介绍
一个社区场馆将已确认的访问记录保存在 Hive 归档中。一次获准更正会替换某个日期的全部已确认记录,而不是把补丁追加到昨天的记录后面。现在,一个获准日期有两条已确认记录,另一个获准日期没有已确认记录。其他日期的数据,包括后来新增的记录,都必须原样保留。
你将先在一次性练习表上比较追加和替换,再保存并执行一个严格限定范围的 SQL 文件来更正真正的 ORC 归档。你还会重复执行同一文件并再次读取结果。环境已经运行 Hive 和 HDFS,并提供相互独立的原始记录、候选更正记录和归档。
你应已了解 Hive 外部表、带有 WHERE 的 SELECT、分区列、ORC 以及基本 HDFS 路径。本实验介绍静态目标分区和整日记录替换。所有操作均在 Terminal 标签中完成。65 分钟是作者估计,包含阅读和普通错误处理时间。
安全比较追加与替换
本步骤先读取一个正常归档日期,再在一次性练习表上比较三种写入范围。比较期间保持真正的归档不变。
打开 Terminal。整个实验都使用已准备的工作目录:
cd /home/labex/project
本地 venue 目录包含参考 CSV 文件和批准清单。cat 会显示文件内容,不会编辑文件:
cat venue/approved-days.txt
2026-10-02
2026-10-03
你只能替换真正归档中的这两个日期。先读取一个正常日期。Beeline 将 SQL 发送给 HiveServer2。下面的命令中,-u 指定 JDBC 连接地址,-n labex 指定客户端用户名,-e 指定 SQL 文本。双引号将整段文本作为一个 shell 参数;其中的单引号用于界定 SQL 值。DATE '...' 明确指定日期类型。
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "SELECT * FROM venue_archive.archive WHERE visit_date=DATE '2026-10-04' ORDER BY visit_id;"
在启动提示下方查看数据行。该日有 v4 / Music / 4 和 v5 / LateWalk / 2。后来新增的 v5 是有效记录,必须保留。镜像可能显示关于多个日志绑定的 SLF4J 提示;它们与 SQL 错误不同。等命令返回提示符后再继续。
现在检查完整候选来源,包括已取消的记录:
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "SELECT * FROM venue_archive.candidate ORDER BY visit_date,visit_id;"
10 月 2 日有 c21 / PrintWorkshop / 5 和 c22 / Bookbinding / 2,状态均为 confirmed。10 月 3 日有一条 cancelled 记录。归档只保存 confirmed 行,因此 10 月 3 日的合法替换记录集为空。筛选结果中没有某个日期,并不表示“保留该日期的旧归档不动”。批准范围与已确认行的筛选条件回答的是不同问题。
检查三张实际表从哪里读取和写入。DESCRIBE FORMATTED 会在列定义之外显示存储元数据:在每份结果中找到 Table Type、Location 和 InputFormat。长输出还包含引擎信息;写入前先关注这些字段。
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "DESCRIBE FORMATTED venue_archive.raw; DESCRIBE FORMATTED venue_archive.candidate; DESCRIBE FORMATTED venue_archive.archive;"
三张表都是 EXTERNAL_TABLE 对象。原始来源的位置是 hdfs://localhost:9000/user/labex/venue-archive/raw;候选来源的位置以 /user/labex/venue-archive/candidate 结尾。两者均使用文本输入。归档位置是 hdfs://localhost:9000/warehouse/external/venue_archive.db/archive,其输入格式以 OrcInputFormat 结尾。本地 venue/*.csv 文件只是参考副本,并非归档。保留给定映射和来源文件。
更改真正归档前,先使用两张一次性练习表:practice_days 按日期分区;practice_whole 将日期保存为普通列。它们最初包含原始来源中的已确认访问记录。以下命令只在这些练习表上有意演示错误结果。
INSERT INTO 会追加记录。PARTITION(visit_date='2026-10-02') 是一个静态目标分区:这个日期字面量决定所有选中记录的写入位置。因此,SELECT 只能返回三个非分区列。独立的 WHERE 条件负责选择来源行。指定目标分区不会自动筛选来源。
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "INSERT INTO TABLE venue_archive.practice_days PARTITION(visit_date='2026-10-02') SELECT visit_id,activity,visitors FROM venue_archive.candidate WHERE visit_date=DATE '2026-10-02' AND record_status='confirmed'; SELECT * FROM venue_archive.practice_days WHERE visit_date=DATE '2026-10-02' ORDER BY visit_id;"
结果包含 c21、c22,**还包括旧的 v2**。SQL 执行成功了,但没有满足替换契约。再次追加相同更正还会产生更多重复行。
INSERT OVERWRITE 会替换目标中已有的行。对于非分区表 practice_whole,目标是整张表。观察其他日期如何消失:
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "INSERT OVERWRITE TABLE venue_archive.practice_whole SELECT visit_id,activity,visitors,visit_date FROM venue_archive.candidate WHERE visit_date=DATE '2026-10-02' AND record_status='confirmed'; SELECT * FROM venue_archive.practice_whole ORDER BY visit_date,visit_id;"
结果只剩下 10 月 2 日的两行。一次成功的整表写入可能悄悄丢失无关日期。现在从完整原始来源恢复这张一次性练习表:
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "INSERT OVERWRITE TABLE venue_archive.practice_whole SELECT visit_id,activity,visitors,visit_date FROM venue_archive.raw WHERE record_status='confirmed'; SELECT * FROM venue_archive.practice_whole ORDER BY visit_date,visit_id;"
原有五行全部恢复。最后,在 practice_days 上将 OVERWRITE 与静态日期分区结合:
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "INSERT OVERWRITE TABLE venue_archive.practice_days PARTITION(visit_date='2026-10-02') SELECT visit_id,activity,visitors FROM venue_archive.candidate WHERE visit_date=DATE '2026-10-02' AND record_status='confirmed'; SELECT * FROM venue_archive.practice_days ORDER BY visit_date,visit_id;"
结果有六行:10 月 1 日的原始记录、更正后的 10 月 2 日两条记录、10 月 3 日的原始记录,以及 10 月 4 日的两条访问记录。旧的 v2 已消失。这就是更正真正归档所需的写入范围。
如果 Beeline 报告表名无效,说明 SQL 没有找到目标对象。使用下面已熟悉的只读命令检查拼写,然后重新执行修正后的命令。文件路径错误可以通过 pwd 和 ls venue 排查;用上面的 cd 命令返回工作目录。不要为了修正拼写而重新创建表或运行环境 setup。
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "SHOW TABLES IN venue_archive;"
检查本步骤前,确认练习分区的 10 月 2 日恰好包含 c21 和 c22,整表练习已恢复五条原始记录,真正归档仍保留原始数据。
替换有已确认记录的获准日期
本步骤将保存并执行真正归档中 10 月 2 日的替换操作。继续在 Terminal 中操作,工作目录为 /home/labex/project。
实际表 venue_archive.archive 是一张非事务型外部 ORC 表,按 visit_date DATE 分区。原始来源和候选来源是相互独立的外部逗号分隔文本表。你只能替换获准的归档日期,不能编辑来源文件、更改表定义或位置、重新映射分区、创建额外日期,或重建整个归档。10 月 1 日和 10 月 4 日必须保留原有数据及现有 HDFS 文件。即使重写完全相同的行,也超出了批准范围。
写入前检查实际分区清单和列布局。SHOW PARTITIONS 列出已登记的日期分区;DESCRIBE 先显示普通列,再显示分区信息:
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "SHOW PARTITIONS venue_archive.archive; DESCRIBE venue_archive.archive;"
四个日期为 10 月 1 日至 4 日。普通列是 visit_id STRING、activity STRING 和 visitors INT;visit_date DATE 是分区列。保留这一映射和 ORC 格式。
将 SQL 保存为可编辑文件,便于检查、修正并重复执行同一操作。nano 是 Terminal 内的文本编辑器。以下命令会在当前工作目录打开 replace-approved-days.sql;这是新文件,因此最初的编辑区为空:
nano replace-approved-days.sql
将下面五行 SQL 输入 nano,不要输入 shell 提示符。单引号界定 SQL 值,分号结束语句。在最后一个分号处停止,不要再添加一个空行;nano 保存时会补上结束换行:
INSERT OVERWRITE TABLE venue_archive.archive
PARTITION(visit_date='2026-10-02')
SELECT visit_id,activity,visitors
FROM venue_archive.candidate
WHERE visit_date=DATE '2026-10-02' AND record_status='confirmed';
用方向键移动到需要修正的字符;Home 和 End 分别移到当前行的开头和末尾。Backspace 删除光标左侧的字符;Delete 删除光标处的字符。在原位输入正确文本。nano 底部的 ^ 表示 Ctrl。按 Ctrl+O 保存:在 File Name to Write 处保留显示的文件名,再按 Enter。然后按 Ctrl+X 退出。等 shell 提示符重新出现;SQL 应输入编辑器,下面的命令才输入该提示符。
执行前先读取保存的内容:
cat replace-approved-days.sql
检查语句中的两个日期:静态目标和来源筛选条件都必须是 10 月 2 日。更正数据是完整的已确认记录集,包含 c21 和 c22 两条记录。无需匹配旧访问 ID,也无需逐行更新。
Beeline 的 -f 从文件读取 SQL。执行保存的文件:
beeline -u jdbc:hive2://localhost:10000/default -n labex -f replace-approved-days.sql
随后像业务读取方一样读取全部四个日期:
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "SELECT visit_date,visit_id,activity,visitors FROM venue_archive.archive ORDER BY visit_date,visit_id;"
预期有六行。10 月 2 日包含 c21 / PrintWorkshop / 5 和 c22 / Bookbinding / 2,不再有 v2。10 月 3 日暂时仍保留旧的 v3。10 月 1 日的 v1 以及 10 月 4 日的 v4、v5 保持不变。
Beeline 连接使用 labex 身份。HiveServer2 以其服务用户 hive 执行存储写入,因此新 ORC 文件可能归 hive:bigdata 所有。无需更改其所有者或权限。HDFS 的 NameNode 使用独立的 hdfs 服务身份运行。
如果 SQL 语句有语法错误,先用 cat 检查保存的文件,再用 nano replace-approved-days.sql 重新打开。用方向键定位 Beeline 错误中指出的语句。按需要修正表名、日期、引号或分号,保留其他 SQL 行。按 Ctrl+O、Enter 保存,再按 Ctrl+X 退出。重新执行 -f 前再次读取文件。如果意外向这个获准日期追加了记录,同样的正确分区覆盖会移除旧行和重复行。这种恢复仅适用于获准日期,不授权你重建受保护日期。
应用空记录集替换并重复执行文件
本步骤将清空获准的 10 月 3 日分区,然后执行两次完整更正文件,验证归档不会累积重复行。继续在 Terminal 中操作,工作目录为 /home/labex/project。
取消活动仍是一种更正。批准清单包含 10 月 3 日,但候选来源中该日没有已确认访问记录。先执行来源筛选:
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "SELECT visit_id,activity,visitors FROM venue_archive.candidate WHERE visit_date=DATE '2026-10-03' AND record_status='confirmed';"
没有返回数据行。最终正确归档中该日也必须没有行。跳过写入会留下旧的 v3。
重新打开同一文件。保留已有的 10 月 2 日语句;你将追加一条语句,不要再次复制第一条:
nano replace-approved-days.sql
用向下方向键移到第一条语句分号后的空行,必要时用 End 到达该行末尾。在这个空行处按一次 Enter,在两条语句之间留一行空行。然后只输入下面五行新内容。在最后一个分号处停止,不要再添加一个空行。如果是在继续中断的编辑,先检查是否已有这条 10 月 3 日语句;修正已有语句,不要重复添加。
INSERT OVERWRITE TABLE venue_archive.archive
PARTITION(visit_date='2026-10-03')
SELECT visit_id,activity,visitors
FROM venue_archive.candidate
WHERE visit_date=DATE '2026-10-03' AND record_status='confirmed';
按 Ctrl+O、Enter 保存,再按 Ctrl+X 退出。在 shell 提示符处读取完整的保存文件:
cat replace-approved-days.sql
检查文件恰好包含两条语句:原来的 10 月 2 日语句在前,新加的 10 月 3 日语句在后。每条语句的静态目标与来源筛选条件都必须指定该语句对应的获准日期。如果有误,在 nano 中重新打开同一文件,只修正受影响的行,然后再次保存并检查。
第一次执行这份完整保存文件:
beeline -u jdbc:hive2://localhost:10000/default -n labex -f replace-approved-days.sql
静态覆盖的查询结果为空时,会移除目标分区中的旧行,同时保留该日期的分区登记。存储引擎决定空分区是否包含物理文件;不要自行创建占位 CSV 或 ORC 文件。
读取已登记的日期和完整结果:
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "SHOW PARTITIONS venue_archive.archive; SELECT visit_date,visit_id,activity,visitors FROM venue_archive.archive ORDER BY visit_date,visit_id; SELECT COUNT(*) FROM venue_archive.archive WHERE visit_date=DATE '2026-10-03';"
四个分区仍全部列出。完整结果有五行:v1、c21、c22、v4 和 v5。10 月 3 日的计数为 0。批准清单包含两个日期,并不意味着两个分区都必须有记录。
现在不改文件,再次执行同一保存文件:
beeline -u jdbc:hive2://localhost:10000/default -n labex -f replace-approved-days.sql
重复业务读取查询:
beeline -u jdbc:hive2://localhost:10000/default -n labex -e "SELECT visit_date,visit_id,activity,visitors FROM venue_archive.archive ORDER BY visit_date,visit_id; SELECT COUNT(*) FROM venue_archive.archive;"
仍是相同的五行,总数为 5。对于给定来源,这种替换可以重复执行,不会追加重复行。重复覆盖可能重新创建获准分区的文件,但非目标日期的原始文件必须保持不动。
你可以使用熟悉的 HDFS 命令检查原始来源。这里的 -cat 读取指定来源文件本身,而不是派生的 ORC 归档:
hdfs dfs -cat /user/labex/venue-archive/raw/raw.csv
其中仍包含原始 v2 和 v3。更改派生归档不会重写原始历史。候选来源和批准清单也必须原样保留。将 SQL 文件保存在工作目录。检查程序观察当前 Hive 数据、定义、范围和受保护文件,不执行任意保存的 SQL。实际重复执行并读取结果,才是对所保存操作的自检。
总结
你比较了追加、整表替换和静态分区替换。随后替换了一个获准日期的完整记录集,应用了合法的空记录集替换,并重复执行同一 SQL 文件而没有累积重复行。独立的原始历史和其他归档日期保持完整。



