从 ODS 到 Materialized View:一文讲透 OLAP 与数据仓库中的核心概念
如果让一个业务数据库回答“某个用户的订单是否已经支付”,它通常只需要通过主键索引读取几行数据。如果让同一个数据库回答“过去一年每个地区、每个品类、每个月的销售额和去重用户数是多少”,问题就完全不同了:它需要扫描大量订单明细,关联商品和地区信息,再执行聚合、排序甚至窗口计算。
前者是典型的 OLTP(Online Transaction Processing,联机事务处理),后者是典型的 OLAP(Online Analytical Processing,联机分析处理)。
很多数仓术语都诞生于同一个矛盾:业务系统擅长记录事实,但不擅长反复解释事实。 ODS、DWD、DWS、ADS 是为了逐步整理事实;维度建模是为了组织分析视角;Cube、Rollup 和 Materialized View 则是在回答另一个问题:能不能不要每次查询都从最细粒度的数据重新算起?
本文从一张订单表开始,把这些概念串成一个完整体系。
目录
- 1. 从业务数据库开始
- 2. Data Warehouse:将分析负载从业务库剥离
- 3. 数仓分层:ODS、DWD、DWS、ADS 与 DIM
- 4. 维度建模:事实表与维度表
- 5. OLAP:在多个维度上观察事实
- 6. 为什么需要预聚合
- 7. Rollup:一个词,两层含义
- 8. Materialized View:从固定汇总表到自动查询改写
- 9. Doris、StarRocks 与 ClickHouse 的实现差异
- 10. Presto 与 Trino:计算存储分离之后
- 11. 从 Cube 到 Cost Based Rewrite
- 12. 工程实践:什么时候应该创建 MV
- 13. 术语表
- 14. 总结
1. 从业务数据库开始
1.1 业务系统首先需要正确地记录状态
假设我们正在开发一个电商系统。最开始,MySQL 中可能有如下几张表:
CREATE TABLE orders (
order_id BIGINT PRIMARY KEY,
user_id BIGINT NOT NULL,
region_id INT NOT NULL,
order_status VARCHAR(32) NOT NULL,
order_time DATETIME NOT NULL,
update_time DATETIME NOT NULL,
KEY idx_user_time (user_id, order_time)
);
CREATE TABLE order_items (
order_id BIGINT NOT NULL,
product_id BIGINT NOT NULL,
quantity INT NOT NULL,
amount DECIMAL(18, 2) NOT NULL,
PRIMARY KEY (order_id, product_id)
);
CREATE TABLE products (
product_id BIGINT PRIMARY KEY,
category_id INT NOT NULL,
product_name VARCHAR(255) NOT NULL
);这套模型首先服务于交易流程:
