DBAtlas · 数据库运维图谱

参考架构:数据仓库 / 分析

分析型查询(报表、聚合、大范围扫描)与 OLTP 事务有本质不同:数量少,但范围很大、运行时间长。这棵决策树从将分析与 OLTP 分离的决策开始,逐步介绍加载方式(ETL vs ELT)、列式/columnstore 存储、星型模型建模、分区 + 压缩以及使用物化视图进行预计算等组件,同时权衡并发与吞吐量之间的取舍。

你的分析负载是否与 OLTP 运行在同一个数据库上?

最常见的错误是在线上事务数据库上运行重型报表,拖累 OLTP 延迟。第一个决策是分离:分析是否仍在 OLTP 实例上运行,你是否正在构建独立的分析环境,还是正在决定如何将数据迁移过去?

  • 报表仍在线上 OLTP 上运行;拖慢了 OLTP
  • 已有独立的数据仓库;应如何加载数据?
  • 已有数据仓库;查询仍然很慢,应如何建模?

在哪里进行转换:加载之前还是之后?

将数据从源系统迁移到数据仓库时,是在加载前于单独的处理层中进行清洗/转换(ETL),还是先将原始数据加载到数据仓库,再在强大的仓库引擎内用 SQL 进行转换(ELT)?该决策取决于数据仓库的处理能力和对模式灵活性的需求。

  • 转换复杂/在外部进行;在加载前完成
  • 数据仓库很强大;原样加载,在内部用 SQL 转换

查询瓶颈在存储布局还是数据模型?

如果分析很慢,有两个主要的着力点。在行式存储中,大范围扫描会读取整行;列式存储只读取所需的列,且压缩效果好。在模型方面,过度规范化意味着大量连接,拖慢查询;星型模型(事实 + 维度)可以为分析简化结构。

  • 大范围聚合扫描很慢;只读取少数几列
  • 连接过多,规范化模式复杂
  • 同一个重型报表反复产生相同的结果

建议:将分析与 OLTP 分离

事务型和分析型负载在同一引擎上会相互拖累:长报表占用锁/IO,延迟短事务。将分析迁移到单独的目标(只读副本或独立的分析型数据仓库)可以同时为两侧减负。

建议:ETL(加载前转换)

在 ETL 中,数据从源系统抽取(Extract),在单独的处理层中进行清洗和转换(Transform),然后才加载到数据仓库(Load)。只有干净的、符合模型的数据才会进入数据仓库。

建议:ELT(在数据仓库内转换)

在 ELT 中,原始数据先加载到数据仓库,转换在数据仓库自身强大的 SQL 引擎内进行。由于现代列式数据仓库处理能力很强,你只需移动一次数据并在内部处理,而不是把转换带到数据那里。

建议:列式 / columnstore 存储 + 压缩

分析型查询通常会扫描所有行中的少数几列。列式存储按列保存数据;它只读取所需的列,由于相似的值彼此相邻而压缩效果极好,IO 大幅下降。

建议:星型模型(事实 + 维度)

在分析模型中,保存度量值的事实表位于中心,周围是描述性的维度表。与过度规范化的模式相比,连接数量减少,查询更简单,引擎能生成更好的执行计划。

建议:用物化视图预先计算

如果同一个重型聚合(每日收入、月度汇总)反复运行并产生相同的结果,将结果物理存储在物化视图中,让报表读取预先计算好的结果。繁重的计算只运行一次,查询即时返回。

在 DBAtlas 中打开 →