4.4 视图与索引:重写与代价


4.4 视图与索引:重写与代价

本节摘要:视图是存放在 Metastore 里的一段查询定义,编译期被原样展开进你的语句,不占任何存储;索引曾经是 Hive 补救随机访问的方案,因为维护成本高、收益不稳定,已让位于分区裁剪与列存跳读。本节用 EXPLAIN 验证视图的展开机制,讲视图的三类工程用法与风险,再解释索引为何退役、物化视图为何登场。

视图是编译期的文本展开

先建一个带业务口径的视图——"高价值客户订单":

CREATE VIEW mall.vip_orders AS SELECT o.order_id, o.customer_id, o.amount, o.dt FROM mall.orders o JOIN mall.customers c ON o.customer_id = c.customer_id WHERE c.vip_level >= 3 AND o.amount > 100;

查询这个视图:

EXPLAIN SELECT dt, COUNT(*) FROM mall.vip_orders WHERE dt = '2026-01-15' GROUP BY dt;

EXPLAIN 输出里找不到任何"视图算子":你看到的是 orders 与 customers 两张物理表的 TableScan、完整的 Join 算子树、以及内外两层 WHERE 合并后的 Filter。视图在语义分析阶段被展开成子查询,之后走的是与手写等价 SQL 完全相同的编译流程。它像一个编译期的宏:定义一次,处处展开。

展开机制推出三条硬性质。第一,视图零存储:查询视图的代价等于查询其定义的代价,一分不多一分不少。第二,视图自带谓词合并:你传进来的 dt 条件与视图内的 vip 条件会在优化器手里一起下推(都有单侧可推的性质时)。第三,视图的编译有绑定风险:底层表改列名,视图当场编译失败;底层表加列且视图用星号,视图含义悄悄漂移。核心视图必须纳入变更管理,这是第 8 章数仓治理的话题。

视图的三类工程用法

口径固化。业务里"活跃用户""高价值订单"这类定义会出现在几十条 SQL 里,口径一变全要改。把口径写成视图,下游统一引用视图名,口径变更只改一处。数仓分层里 DWS 层对 DWD 层的轻度汇总,经常先以视图形态存在,验证稳定后再物化成表。

权限与安全边界。敏感列不希望全员可见——建一个脱敏视图(手机号只露后四位),普通分析师授权到视图,底层表权限收紧:

CREATE VIEW mall.orders_masked AS SELECT order_id, concat('****', substr(phone, 8, 4)) AS phone_masked, amount FROM mall.orders_raw;

兼容层。表重构(拆表、改列名、迁移库)期间,旧表名以视图形态指向新结构,下游 SQL 无感过渡。这个用法让"改表不断服务"成为可能,代价是视图链不能嵌套太深——每层展开都发生在编译期,十层嵌套的视图既难读也会拖慢编译。

视图的使用边界也要直说:它解决"逻辑复用",不解决"重复计算"。同一视图被一百条查询引用,那一百次查询各自把 Join 与过滤算一遍。要共享计算结果,得用物化。

物化视图:把展开的结果存下来

Hive 3 引入物化视图(Materialized View),机制与传统数据库同思路:视图定义加上一份实际存储:

CREATE MATERIALIZED VIEW mall.mv_region_daily AS SELECT dt, region, COUNT(*) AS cnt, SUM(amount) AS amt FROM mall.orders GROUP BY dt, region;

(拼写以实际版本的 CREATE MATERIALIZED VIEW 为准。)

它带来一个编译期新玩法——自动改写:查询"每天每地区的订单量"时,优化器发现这条查询可以从 mv_region_daily 的结果推出来,会自动改写为查物化视图本身,扫描量骤降。EXPLAIN 里你会看到 TableScan 的 alias 变成了物化视图名,这是改写生效的指纹。

代价是维护:底表更新后物化结果过期,要么定时重建,要么依赖增量刷新(版本相关能力,对 ORC 与特定聚合支持最好)。物化视图适合"高频查询加底表缓慢变化"的报表场景,与第 7 章的 LLAP 缓存属于同一战壕的两种武器。

索引:一个退役方案的前因后果

老资料里的"索引操作"章节会教你建 Bitmap 或 Compact 索引:

CREATE INDEX idx_customer ON TABLE mall.orders(customer_id) AS 'COMPACT' WITH DEFERRED REBUILD;

思路是给列建一份"值到文件位置"的辅助表,点查时先查索引缩小扫描范围。听起来合理,实践里三个缺陷叠满:

  • 维护税:每次写入底表都要同步更新索引表,批处理吞吐直接受损;
  • 收益窄:Hive 的查询绝大多数是全表扫描加聚合的分析型负载,索引只对高选择性点查有效,而这恰是 Hive 最不擅长的场景;
  • 替代品出现:分区裁剪在目录层解决裁剪,ORC 与 Parquet 在文件内建了轻量索引(每块的最小最大值、布隆过滤器),按列统计支撑 CBO——三层机制把索引的生存空间挤没了。

Hive 3 已经移除了独立的索引语法(ORC 内建索引与物化视图接棒)。看到老集群里的索引表,当作历史遗留处理;新设计一律走"分区加列存加统计"的组合。

把三样武器放进同一张决策表

工具 存储成本 收益场景 维护动作
分区 目录元数据 按时间等维度裁剪扫描 分区生命周期管理
分桶加桶内排序 无额外 布局即成本 大表连接免 Shuffle 桶抽样 灌数纪律与布局体检
视图 口径复用 权限边界 兼容层 底表变更时同步改
物化视图 一份结果存储 高频重复查询自动改写 定期或增量刷新
索引 辅助表 已退役 高选择性点查 不再新建 逐步下线

决策顺序建议:先问分区能不能解决(最便宜),再问列存与统计够不够(默认组合),再考虑分桶(有明确连接场景才值得),最后才是物化视图(有高频重复查询的证据才建)。每一步都可以用第 3 章的六问清单验证收益是否真的落进了执行计划。

本节要点回顾

  • 视图即展开:编译期宏替换,零存储,EXPLAIN 里只有底层表的痕迹;
  • 三类用法:口径固化、脱敏与权限边界、重构期的兼容层,嵌套别太深;
  • 绑定风险:底层表变更会传导到视图,核心视图纳入变更管理;
  • 物化视图:存结果加自动改写,适合高频查询加缓变底表,代价是刷新维护;
  • 索引已退役:维护税高、收益窄,被分区、列存内建索引、统计信息三方取代;
  • 决策顺序:分区先于列存统计,列存统计先于分桶,分桶先于物化。

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