1.3 环境搭建与第一条EXPLAIN


1.3 环境搭建与第一条 EXPLAIN

本节摘要:搭一套能跑通"建表、装数、查询、EXPLAIN"完整链路的环境。给出三套方案(容器、伪分布式、直连已有集群)的取舍,列出最小可用的关键配置,最后用一张小表打出第一条执行计划并逐行认读,为第 3 章的 EXPLAIN 精读做铺垫。

三套方案,按目的选

搭环境的第一个决定不是"装哪个版本",而是"你要它干什么"。目的不同,方案完全不同:

  • 只想跟着本教程敲 EXPLAIN:用容器方案,一条命令起一个带 Hive 的沙箱,十分钟可用,用完即弃;
  • 要完整练习 HDFS、YARN、Metastore 的联动:伪分布式方案,一台机器装全套,过程繁琐但每一层都摸得到;
  • 公司已有集群:什么都不用装,找运维要 Beeline 地址与账号直连,注意只在自己名下的测试库做实验。

三套方案的共同底线是版本:建议 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。关键步骤与要点:

  1. Hadoop 伪分布式:NameNode、DataNode、ResourceManager、NodeManager 全部起在本机,jps 确认四个进程齐活;
  2. MySQL 建库授权:create database metastore default charset latin1;——字符集用 latin1 是老坑,MySQL 8 的 utf8mb4 会让部分版本的 schema 初始化报错,遇到再查对应版本的兼容说明;
  3. 初始化元数据库后,把关键参数写进服务器配置(hive-site.xml,这里展示最重要的几项):
<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

正餐来了。对刚才的表执行:

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)

第一次不用全看懂,先抓四个锚点:

  • Vertex dependency 是计划的总纲:Map 1 与 Reducer 2 两个顶点、一条边,就是"先并行扫、再按键汇总"的图形化表达。MR 引擎下对应 STAGE DEPENDENCIES,语义相同;
  • TableScan 与 alias 告诉你扫的是哪张表的哪个别名,多表查询时用它核对每张表挂在哪条分支;
  • Filter 的 predicate 是谓词下推的着陆点:amount 大于 50 这个条件出现在 Map 端 Select 之后,意味着不合格的行在进入网络前就被丢掉。注意 dt 这个条件没有出现在 predicate 里——它被翻译成了分区裁剪,直接把扫描范围从"全表"收缩到"一个分区目录",这比任何过滤都便宜;
  • mode: hash 与 mergepartial 是 GroupBy 的两段式聚合:Map 端先各自预聚合(把同键的行先压成部分结果),Shuffle 传输的因此是"每键一条部分和"而不是原始行,网络量大幅下降。这个机制第 6 章细讲。

把这四个锚点记住,你已经能对任何简单查询回答三个问题:扫几张表、过滤在哪端做、聚合分几段。这就是"看懂翻译"的起点

EXPLAIN 的三个伙伴

EXPLAIN 还有两个扩展形态与一个反面教训:

  • EXPLAIN EXTENDED:附加更详细的算子参数、表达式字符串与路径信息,排错时用来核对 SerDe 与路径;
  • EXPLAIN ANALYZE(Hive 2.2 之后):真的执行查询,并在计划旁标注每个算子的实际返回行数与耗时,用来对比"估算"与"现实",是查数据倾斜的铁证;
  • 反面教训:EXPLAIN ANALYZE 会真跑任务,对大表慎用;习惯上先 EXPLAIN 看结构,确认代价可控再上 ANALYZE。

另外一个小技巧:把 EXPLAIN 输出贴进团队文档或工单里时,务必带上查询文本与引擎参数(SET hive.execution.engine; 的结果),否则两周后你自己都读不懂当时的环境。

本节要点回顾

  • 按目的选环境:学计划用容器沙箱最快,学架构用伪分布式,有集群直连但要隔离到个人测试库;
  • 版本建议 3.x:EXPLAIN 格式与增强特性以 2.x 之后为基准;
  • 小数据集足够学编译:计划骨架与数据量无关,统计信息的偏差留给 CBO 章节;
  • EXPLAIN 四锚点:顶点依赖、TableScan 别名、Filter 谓词位置、GroupBy 的 mode 标记;
  • 谓词与裁剪的区别:amount 条件翻译成 Map 端过滤,dt 条件翻译成分区裁剪,后者成本为零;
  • ANALYZE 会真执行:大表上先 EXPLAIN 后 ANALYZE,两步走。

第 1 章到此收尾。你已经能搭环境、建表、看计划骨架。第 2 章钻进 Driver 内部,看这四道翻译工序各自怎么做手术。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U