本节摘要:搭一套能跑通"建表、装数、查询、EXPLAIN"完整链路的环境。给出三套方案(容器、伪分布式、直连已有集群)的取舍,列出最小可用的关键配置,最后用一张小表打出第一条执行计划并逐行认读,为第 3 章的 EXPLAIN 精读做铺垫。
搭环境的第一个决定不是"装哪个版本",而是"你要它干什么"。目的不同,方案完全不同:
三套方案的共同底线是版本:建议 Hive 3.x(CDH 6.x、HDP 3.x 或 Apache Hive 3.1),因为第 2、3 章的 EXPLAIN 输出格式、第 6 章的物化视图与增强聚合都以 2.x 之后的能力为基准。Hive 1.x 的输出格式差异较大,对照读会困惑。
社区维护的 Hive 镜像里预置了内嵌 Metastore 与演示数据。启动后直接进入 Beeline:
docker run -d --name hive-sandbox -p 10000:10000 -p 10002:10002 hive:3.1.3 docker exec -it hive-sandbox beeline -u jdbc:hive2://localhost:10000
进去后执行 show databases; 能列出 default 库即成功。缺点是单容器里 YARN 是 Local 模式,任务实际在本机进程里跑,看不到真实的多节点调度;但对学编译与执行计划毫无影响——计划是 Driver 生成的,与任务在哪跑无关,这正是本教程主线最依赖的能力。
在一台 Linux 机器上按顺序装 JDK、Hadoop、MySQL、Hive。关键步骤与要点:
jps 确认四个进程齐活;create database metastore default charset latin1;——字符集用 latin1 是老坑,MySQL 8 的 utf8mb4 会让部分版本的 schema 初始化报错,遇到再查对应版本的兼容说明;<configuration> <property> <name>javax.jdo.option.ConnectionURL</name> <value>jdbc:mysql://localhost:3306/metastore?createDatabaseIfNotExist=true</value> </property> <property> <name>hive.metastore.uris</name> <value>thrift://localhost:9083</value> </property> <property> <name>hive.execution.engine</name> <value>tez</value> </property> </configuration>
三个参数对应上一节的架构图:元数据库连接(Metastore 后端)、Metastore 服务地址(远程模式)、默认执行引擎。装好后按顺序启动 Metastore 服务与 HiveServer2,再用 Beeline 连接。
拿到 jdbc 地址后唯一要注意的是工作库隔离:先 CREATE DATABASE mydemo; 再 USE mydemo;,全部实验在自己库里做。集群默认引擎与参数由平台统一管理,个人不要随意改全局参数,SET 只影响当前会话。
环境通了,造一张贯穿全册的表。场景是电商订单明细,先来一个五行数据的小份:
CREATE DATABASE IF NOT EXISTS mydemo; USE mydemo; CREATE TABLE orders ( order_id BIGINT, customer_id STRING, region STRING, amount DECIMAL(10,2) ) PARTITIONED BY (dt STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ','; INSERT INTO orders PARTITION (dt = '2026-01-15') VALUES (1001, 'c001', 'north', 230.00), (1002, 'c002', 'south', 99.50), (1003, 'c001', 'north', 480.00), (1004, 'c003', 'east', 120.00), (1005, 'c002', 'south', 65.00);
五行数据足够了。编译器生成执行计划不需要大数据量——翻译官翻译一页稿子和翻译一本书,用的是同一本词典和同一套语法。数据量影响的是统计信息与 CBO 的估算(第 7 章),不影响计划骨架。
顺带看一眼这张表在 HDFS 上的真身:
DESCRIBE FORMATTED orders;
输出里的 Location 字段就是表目录,进 HDFS 看,dt 为 2026-01-15 的分区是一个子目录,里面躺着 INSERT 生成的数据文件。"表即目录、分区即子目录"这句口诀,第 4 章会展开成完整的设计方法论。
正餐来了。对刚才的表执行:
EXPLAIN SELECT region, COUNT(*) AS cnt, SUM(amount) AS amt FROM orders WHERE dt = '2026-01-15' AND amount > 50 GROUP BY region;
输出(Tez 引擎、Hive 3.x 典型格式,注释是后加的):
Plan not optimized by CBO. -- CBO 未启用,走规则优化器 Vertex dependency in root stage Map 1 <- Reducer 2 [SIMPLE_EDGE] -- 顶点依赖:Map 1 输出喂给 Reducer 2 Stage: Stage-1 Tez Map 1 Map Operator Tree: TableScan -- 扫表算子 alias: orders Statistics: Num rows: 5 Data size: 300 GatherStats: Aggregate Select Operator expressions: region (type: string), amount (type: decimal(10,2)) outputColumnNames: _col0, _col1 Filter Operator predicate: (amount > 50) (type: boolean) Reduce Operator Tree: Group By Operator aggregations: count(), sum(_col1) keys: _col0 (type: string) mode: hash -- 第一阶段聚合:Map 输出侧预聚合 Reducer 2 Reduce Operator Tree: Group By Operator aggregations: count(), sum(_col1) keys: _col0 (type: string) mode: mergepartial -- 第二阶段聚合:合并各任务的部分结果 Select Operator expressions: _col0 (type: string), _col1 (type: bigint)
第一次不用全看懂,先抓四个锚点:
把这四个锚点记住,你已经能对任何简单查询回答三个问题:扫几张表、过滤在哪端做、聚合分几段。这就是"看懂翻译"的起点。
EXPLAIN 还有两个扩展形态与一个反面教训:
EXPLAIN EXTENDED:附加更详细的算子参数、表达式字符串与路径信息,排错时用来核对 SerDe 与路径;EXPLAIN ANALYZE(Hive 2.2 之后):真的执行查询,并在计划旁标注每个算子的实际返回行数与耗时,用来对比"估算"与"现实",是查数据倾斜的铁证;另外一个小技巧:把 EXPLAIN 输出贴进团队文档或工单里时,务必带上查询文本与引擎参数(SET hive.execution.engine; 的结果),否则两周后你自己都读不懂当时的环境。
第 1 章到此收尾。你已经能搭环境、建表、看计划骨架。第 2 章钻进 Driver 内部,看这四道翻译工序各自怎么做手术。