列式存储应优先放在分析型数据存储层,计算层负责减少读取并完成聚合,缓存层负责复用高频结果。更准确地说,列式存储属于物理存储与数据组织方式,不应与 ODS、DWD、DWS、ADS 这些逻辑数据层并列。
大数据技术架构本身横跨数据采集、存储、处理、分析、治理和服务等环节;一种数据仓库五层参考模型,也将数据存储层与报表、OLAP 应用层分开。因此,所谓“放在哪一层”,实质上是在讨论三个不同问题:分析数据采用什么格式组织、查询引擎如何减少读取、已有结果如何复用。
先分清逻辑数据层与列式文件
业务源库、ODS、DWD、DWS、ADS 承担的职责不同,列式存储的适用范围也不同。
| 数据位置 | 主要职责 | 列式存储建议 |
|---|---|---|
| 业务源库 | 事务写入、更新、删除、主键点查 | 保留适合事务负载的存储方式,不因报表需求整体迁移 |
| ODS | 接收原始数据,保留明细或原始事件,供清洗、审计与重算使用 | 大规模历史数据、行为日志可采用 Parquet、ORC 等列式文件 |
| DWD | 清洗、标准化后的明细数据,承接关联、下钻和灵活分析 | 通常是列式存储重点所在,尤其是字段较多、扫描范围较大的事实明细 |
| DWS | 按主题组织的汇总数据,承载稳定口径和重复计算 | 大规模汇总可继续采用列式格式;小规模结果可由更适合服务查询的存储承载 |
| ADS | 面向报表、看板或数据服务的输出数据 | 扫描型结果适合列存;高并发、参数有限的固定结果可配合专用服务存储或缓存 |
资料中的分层实践以 ODS 使用 Parquet、清洗明细层使用 ORC 为例。另一份资料也指出,数据存储层可以采用关系数据库、分布式数据库或列式存储,并通过分区、索引、压缩和去重等技术提高存储效率与查询性能。这些内容说明,列式存储既可以是一套数据库,也可以是建立在文件系统或对象存储之上的数据格式。
业务源库和列式分析库承担的是不同负载。源库需要稳定处理写入、事务与主键点查;报表则需要读取大量行、少量列并进行聚合。为了后者而把整个事务库迁移为列式存储,通常会混淆两种工作负载。更合理的路径是通过批量同步或 CDC 将数据送入 ODS,再由分析链路逐步清洗和建模。参考资料也将 CDC、批量同步以及实时和离线处理作为大数据链路中的不同组件。
ODS 是否列式化,取决于数据规模和回放需求。体量较大的日志、事件和历史快照采用列式文件,便于批量读取和压缩;如果只是少量配置或控制数据,没有必要为了技术统一强行转换。五层架构资料同样将关系型数据库或列式数据库都视为数据存储层的可选实现,而不是固定要求。
DWD 是最需要考虑列式存储的逻辑层。它既承接清洗后的明细,又要支持任意日期、多个维度和不同口径的下钻查询。与其提前把大量维度组合全部做成宽表或汇总表,不如先让列式明细具备高效的过滤、投影和聚合能力,再为高频组合建立 DWS 或 ADS。
DWS 和 ADS 不必统一使用同一种物理格式。大规模主题汇总和报表数据集仍然适合列式组织;数据量较小、以固定结果读取为主的服务表,则可以采用更适合点查的存储方式。参考资料中“Redis 缓存高频结果、ClickHouse 承载分析、Spark 处理冷数据”的组合,本质上也是按访问特征分配存储与计算,而不是要求所有数据进入同一种数据库。
因此,“列式存储贯穿分析链路”是一项有条件的架构判断:链路中的大体量明细与汇总数据可以普遍采用列式格式,但小型维表、事务数据、元数据和高并发结果服务仍应按实际负载选择存储方式。
全表扫描不能只靠换存储解决
报表任务被描述为“扫大表”,不一定意味着查询真的读取了整张表的全部列和全部分区。列式存储可以为列裁剪、分区裁剪、压缩读取和聚合下推提供条件,但最终效果仍取决于数据建模方式、分区设计、查询语句和执行引擎。数据存储层需要考虑分区、索引、压缩等因素,查询侧也需要配合过滤与预聚合。
一份固定日报如果只查询大宽表中的少数字段、限定少数日期,并反复计算相同指标,那么它实际上需要的是一条“少读且少算”的固定查询路径。日期、租户或业务分区字段应首先用于分区裁剪,查询只保留真正需要的列;固定过滤条件应尽量下推,能够提前完成的过滤和聚合也不应全部留到最终结果阶段。
列式存储能够减少无关列的读取,但如果查询不能有效裁剪分区,或者每张报表都重复扫描多年明细并进行复杂关联,换成列存只能降低部分成本,不能消除重复计算。对于每天固定运行、指标口径稳定、又被大量用户访问的日报或月报,更适合将公共计算固化到 DWS 或 ADS,日常查询直接读取结果;需要核对明细或临时更换口径时,再回到 DWD 列存数据。
临时下钻面对的是另一类问题。用户可能组合任意日期、地区、渠道、商品或客户维度,如果提前物化所有组合,规模会迅速膨胀。我的判断是,应保留少量高频公共汇总,同时让长尾查询回到 DWD 明细,通过分区裁剪、列裁剪和过滤、聚合下推控制读取量,而不是为每一种维度组合生成一张结果表。
多张事实表与维度表关联时,列式存储可以降低明细读取成本,却不能消除运行期 Join 的开销。高频且口径稳定的关联结果可以适度物化;小维度是否广播、复制或预连接,则应结合执行引擎和实际计划判断。列式数据库并不天然意味着所有 Join 都昂贵,真正需要避免的是大量明细在查询期间反复关联,或者把本可提前完成的转换留到每次请求中。
跨数据源联邦查询适合临时探索和低频整合。参考资料将 Presto 列为支持多数据源联邦查询的交互式分析工具。但如果同一份跨源报表每天被高频提交,运行期数据搬运、源端负载和数据语义差异就会成为主要约束。此时,把所需数据提前集成到 DWD 或 DWS,通常比每次跨源 Join 更容易控制;低频查询则可以保留联邦能力,避免为少量场景复制大量数据。
物化时机需要权衡查询时间与维护成本。基于列存储的大数据分析研究将物化策略区分为早期物化、延迟物化和混合物化。早期物化把聚合提前完成,换取更短的查询时间,但会增加中间数据、写入频率和更新成本;延迟物化保留更多明细,在查询时计算,灵活但扫描和计算量更高;混合物化则让稳定、高频的结果提前生成,让长尾查询回源明细。
实时看板与 T+1 报表也不应被强行放进完全相同的扫描路径。实时链路通常通过流处理或增量计算持续更新面向看板的汇总数据,查询侧再访问服务型存储;T+1 报表则可以使用批处理对历史明细进行重算。参考资料分别列出了实时采集、流处理、离线 SQL 和交互式分析等组件。二者可以共享底层数据和部分列式存储,但应隔离执行队列与资源占用,避免实时查询被长批任务拖慢,长批任务也不能持续争抢看板服务资源。
热、温、冷数据是另一条分层轴,不等同于 ODS、DWD、DWS、ADS。资料将数据创建时间、业务重要性和访问频率作为判断数据冷热程度的依据,并提出热数据查询、温数据分析和冷数据离线处理的组合路径。更通用的设计应综合时效要求、访问频率、扫描量、数据价值和成本,不应机械套用固定天数。
热数据通常需要更低延迟和更高并发,可以采用列式服务存储并配合结果缓存;温数据以交互式下钻为主,更适合由 OLAP 引擎扫描列式明细;冷历史数据则可以保存在成本更低的存储介质上,通过离线引擎按需读取。无论物理介质如何变化,列式文件仍能减少实际访问的列,但冷数据还需要认真设计分区和裁剪,否则“便宜地扫描全部数据”依然昂贵。
高频结果才值得进入缓存
结果缓存应放在数据访问层或应用服务侧,而不是被当作 ODS、DWD、DWS、ADS 之间的新数据层。数据访问层可以通过缓存降低查询延迟,服务层则需要处理访问控制与缓存一致性。
物化结果和结果缓存虽然都可能保存聚合数据,但两者职责不同:
| 对比维度 | 物化结果 | 结果缓存 |
|---|---|---|
| 主要目的 | 固化稳定口径,服务多个查询 | 复用某个具体请求的已有结果 |
| 常见位置 | DWS、ADS 或独立服务数据集 | 数据访问服务、API 网关附近 |
| 数据组织 | 通常有明确表结构、模型和血缘 | 通常按查询参数或请求键保存 |
| 更新方式 | 由数据任务重新计算并发布 | 数据变化后失效或切换版本 |
| 缓存未命中 | 读取物化结果或分析型明细 | 回到上游查询路径重新计算 |
只有同时具备“计算成本较高、重复频率较高、参数空间相对有限、结果可以复用、失效边界可识别”这几个条件时,缓存才容易产生稳定收益。高频固定看板、参数有限的排行榜和重复提交的经营日报适合进入缓存;日期、维度和筛选条件几乎每次都不同的临时查询,如果大量写入缓存,往往只会占用空间,并不能提高命中率。
缓存键至少需要表达数据集身份、数据版本、查询语义、筛选条件、时间范围、时区、返回字段以及必要的租户和权限范围。否则,同一个 URL 在数据更新、指标口径变更或用户权限不同的情况下,可能错误复用同一份结果。缓存内容还应记录生成时间和有效期,便于服务判断数据新鲜度。
数据更新后,不能只靠设置一个较长的生存时间来处理失效。DWD、DWS 或 ADS 的新分区成功发布后,可以切换相应数据集版本,并让新请求使用新的缓存键;旧版本再按策略过期或清理。对于无法精确获知更新事件的场景,生存时间可以作为兜底,但需要结合报表允许的延迟确定。
物化结果本身也应具备版本信息。数据任务至少需要能够追踪源数据水位或截止时间、运行批次、数据模式以及指标口径版本。只有这样,查询服务才能判断某个结果是否对应当前数据,缓存也才能随着数据集版本变化,而不是依赖人工删除。
当相同筛选条件被高并发重复提交时,还会出现缓存失效瞬间的击穿:大量请求同时发现缓存未命中,并一起去扫描明细或计算相同结果。请求合并是更合适的处理方式:同一缓存键只允许一个请求刷新,其他请求等待结果;如果业务允许短暂陈旧,可以在刷新期间返回有明确时间界限的旧版本。
低频查询在缓存未命中后,应直接回到物化结果或 DWD 列存明细,不应默认把查询结果写入缓存。还可以根据访问频率、预计计算成本和参数基数控制缓存准入,避免大量一次性查询占用缓存空间。缓存只能减少重复计算,不能替代分区、索引、预聚合和列式存储;如果缓存未命中后的回源路径仍然昂贵,整体响应时间就不会得到根本改善。
参考资料提供的一种组合是:Redis 保存高频查询结果,ClickHouse 承载分析查询,Spark 处理离线或冷数据。这里值得借鉴的不是具体产品名称,而是职责拆分:固定结果优先复用,交互式查询扫描分析型明细,大范围历史计算交给离线引擎。实时看板的缓存可以随流式结果发布而更新,T+1 缓存则随批任务版本发布而切换;临时下钻缓存未命中时,再根据时间范围选择实时服务表、分析型明细或冷数据离线查询。
在报表架构中,列式存储解决“怎样组织数据”,计算解决“需要读取多少”,缓存解决“是否可以避免重复计算”。比层级归属更关键的是,把这三个问题分别落实到数据模型、执行链路和访问服务中。
[email protected]
。
我们承诺在核实信息后,将第一时间删除相关内容或断开链接。





















暂无评论内容