惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园 - Franky
N
Netflix TechBlog - Medium
宝玉的分享
宝玉的分享
Google DeepMind News
Google DeepMind News
腾讯CDC
G
Google Developers Blog
Martin Fowler
Martin Fowler
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
爱范儿
爱范儿
Engineering at Meta
Engineering at Meta
Microsoft Azure Blog
Microsoft Azure Blog
A
About on SuperTechFans
aimingoo的专栏
aimingoo的专栏
有赞技术团队
有赞技术团队
Jina AI
Jina AI
人人都是产品经理
人人都是产品经理
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
M
MIT News - Artificial intelligence
罗磊的独立博客
博客园 - 三生石上(FineUI控件)
美团技术团队
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志

博客园 - 哥本哈士奇(aspnetx)

dbt+SQLServer构建数据仓库(13):运维 FAQ 篇 dbt+SQLServer构建数据仓库(12):进阶 FAQ 篇 dbt+SQLServer构建数据仓库(11):FAQ 篇 dbt+SQLServer构建数据仓库(10):macro 以及 data vault的应用实例 dbt+SQLServer构建数据仓库(9):用Vibe Coding创建一个DBT UI dbt+SQLServer构建数据仓库(8):Vibe Coding用dbt构建data vault数仓 dbt+SQLServer构建数据仓库(7):进阶扩展 dbt+SQLServer构建数据仓库(6):Jinja与DAG实战 dbt+SQLServer构建数据仓库(5):数据测试 dbt+SQLServer构建数据仓库(4):分层建模实战 dbt+SQLServer构建数据仓库(3):dbt_project.yml配置精讲 dbt+SQLServer构建数据仓库(2):与传统方案对比及迁移决策 dbt+SQLServer构建数据仓库(1):认识dbt与项目工作流程 SQL Server 索引知识汇总 医疗器械行业 Salesforce Territory 完整落地实例 Raw Data Vault vs Business Data Vault Neo4j 多跳查询实战:从社交网络场景理解图遍历 Git 本地版本管理学习笔记 看完《低智商犯罪》,学习Cypher构建知识图谱 LangChain DeepAgents 学习笔记 LangChain Deepagent 版本0.6.1中间件一个bug Neo4j笔记(五):查询的处理流程 微软 SQL Server 版本演进史:从诞生到 SQL Server 2025 提升 Text2SQL 准确率 SQLServer Management Studio(SSMS) 22 Copilot 最佳实践学习笔记 SQLServer RAG笔记4:从服务层到前端交互 SQLServer RAG笔记5:为SQLServer 2025配置Ollama SQL Server RAG 笔记3:SQLServer2025 向量数据库 详解传统RAG、Text2SQL、Graph RAG:适用场景与问题示例汇总 SQL Server RAG 笔记2:图数据库服务层与前端可视化构建
数据仓库笔记 第一篇:数据仓库的定义、历史与意义
哥本哈士奇(aspnetx) · 2026-04-27 · via 博客园 - 哥本哈士奇(aspnetx)

数据仓库笔记 第一篇:数据仓库的定义、历史与意义


摘要

数据仓库(Data Warehouse,简称 DW 或 DWH)是一个面向主题的、集成的、非易失的、随时间变化的数据集合,用于支持管理决策。

此笔记使用的数据库为SQLServer,相应的示例脚本都围绕于此,其它数据库的相应实现会略有不同。

数据仓库的定义来自 Bill Inmon(数据仓库之父),四个核心特征解释如下:

特征 说明
面向主题(Subject-Oriented) 围绕业务主题组织数据,如销售、客户、产品,而非围绕应用系统
集成(Integrated) 将来自多个异构数据源的数据统一整合,消除不一致性
非易失(Non-Volatile) 数据一旦进入仓库,通常不会被修改或删除,只会追加
随时间变化(Time-Variant) 保存历史数据,支持时间维度的分析

数据仓库 vs 数据库(OLTP vs OLAP)

数据仓库也是一种数据库,那么它跟我们平时说的有什么区别呢?

这里就需要引入两个概念,OLTP和OLAP。

┌─────────────────────────────────────────────────────────────┐
│              OLTP(操作型数据库)                              │
│  目的:支持日常业务操作(增删改查)                              │
│  特点:高并发、低延迟、数据量小、范式化设计                       │
│  示例:订单系统、用户系统、库存系统                              │
└─────────────────────────────────────────────────────────────┘
                          ↓ ETL
┌─────────────────────────────────────────────────────────────┐
│              OLAP(数据仓库)                                  │
│  目的:支持分析决策(聚合、趋势、报表)                           │
│  特点:低并发、大数据量、历史数据、反范式设计                      │
│  示例:销售分析、用户行为分析、财务报表                           │
└─────────────────────────────────────────────────────────────┘

数据仓库的历史

时间线

1970s  ── 决策支持系统(DSS)萌芽,数据分析需求出现
1980s  ── 信息中心(Information Center)概念,数据抽取工具出现
1988   ── Barry Devlin & Paul Murphy 首次提出"数据仓库"概念
1990   ── Bill Inmon 正式定义数据仓库,被称为"数据仓库之父"
1993   ── Ralph Kimball 提出维度建模(Dimensional Modeling)
1996   ── Ralph Kimball 出版《The Data Warehouse Toolkit》
2000s  ── ETL 工具成熟(Informatica、DataStage),数据仓库普及
2006   ── Hadoop 出现,大数据时代开始
2010s  ── 云数据仓库兴起(Redshift 2012、BigQuery 2010、Snowflake 2014)
2015   ── Data Vault 2.0 发布(Dan Linstedt)
2020s  ── 数据湖仓一体(Lakehouse)架构兴起(Delta Lake、Iceberg)

关键人物

  • Bill Inmon:数据仓库之父,提出企业信息工厂(CIF)架构,自顶向下设计
  • Ralph Kimball:维度建模大师,提出星型模式,自底向上设计
  • Dan Linstedt:Data Vault 创始人,提出高度可扩展的建模方法

数据仓库的意义

业务价值

没有数据仓库的世界:
  ┌──────────┐    ┌──────────┐    ┌──────────┐
  │ 销售系统  │    │ 财务系统  │    │ CRM系统   │
  │ (MySQL)  │    │ (Oracle) │    │ (SQL Svr)│
  └──────────┘    └──────────┘    └──────────┘
       ↓                ↓               ↓
  各自为政,数据孤岛,无法跨系统分析,报表打架

根据我的经验,没有数据仓库的话会有一个大坑。比如你要跨这些系统去做一个统计,涉及到的数据很大,比如需要五分钟,那么在这五分钟之内,源业务系统就被阻塞了,进行不了任何业务。这个损失是很大的,而且你不可能一天只运行一次查询,每次查询都会导致系统被阻塞。


有了数据仓库的世界:
  ┌──────────┐    ┌──────────┐    ┌──────────┐
  │ 销售系统  │    │ 财务系统  │    │ CRM系统   │
  └──────────┘    └──────────┘    └──────────┘
       └──────────────┼───────────────┘
                      ↓
              ┌───────────────┐
              │   数据仓库     │
              │  统一、清洗、  │
              │  整合、历史    │
              └───────────────┘
                      ↓
         BI报表 / 数据分析 / 机器学习

有了数据仓库,数据都是为了报表提前聚合好的,而且在数据仓库上怎么折腾,也不会拖累到业务系统的性能。

所以总体来说,数据仓库的核心价值就在于:

  1. 统一数据口径:全公司用同一套数据,消除"数据打架"
  2. 历史数据保存:支持趋势分析、同比环比
  3. 性能隔离:分析查询不影响业务系统
  4. 数据质量:清洗、标准化、去重
  5. 决策支持:为管理层提供可靠的数据基础

数据仓库的整体流程

数据源层          采集层           存储层              消费层
─────────        ──────          ──────              ──────
业务数据库  ──┐
日志文件    ──┤   ETL/ELT    ┌── PSA层  ──┐
API接口    ──┤  ──────────► │   DV层      │──► BI工具
Excel文件  ──┤              │   DM层      │──► 报表系统
爬虫数据   ──┘              └─────────────┘──► 数据科学

用 SQL Server 创建数据仓库基础环境

本教程使用 SQL Server,采用每层一个独立数据库的架构。

分库架构总览

┌──────────────────────────────────────────────────────────────────┐
│                     SQL Server 实例                               │
│                                                                  │
│  ┌──────────────┐                                                │
│  │ business_db  │ ← OLTP 业务系统(演示用源系统)                  │
│  └──────────────┘                                                │
│         ↓ Extract(直接抽取)                                     │
│  ┌──────────────┐                                                │
│  │   psa_db     │ ← PSA 层:持久化暂存,保留全部历史               │
│  └──────────────┘                                                │
│         ↓ Transform(维度建模,SCD Type 2)                       │
│  ┌──────────────┐                                                │
│  │  star_db     │ ← Star Schema 层:事实表 + 维度表               │
│  └──────────────┘                                                │
│         ↓ Aggregate(按业务域聚合)                               │
│  ┌──────────────┐                                                │
│  │  mart_db     │ ← Data Mart 层:面向业务的数据集市               │
│  └──────────────┘                                                │
│                                                                  │
│  ┌──────────────┐                                                │
│  │   etl_db     │ ← ETL 日志库(跨层共享)                         │
│  └──────────────┘                                                │
│                                                                  │
│  跨库引用方式:database.dbo.table                                 │
└──────────────────────────────────────────────────────────────────┘

为什么每层用独立数据库?

优势 说明
安全隔离 每层可独立设置访问权限,用户只能访问授权的层
性能隔离 ETL 写入不影响分析查询,IO 互不干扰
备份恢复 可按层独立备份/恢复,粒度更细
存储管理 不同层可放在不同文件组/磁盘,优化 IO
迁移灵活 可将某一层迁移到其他服务器,不影响其他层

创建各层数据库

-- ============================================================
-- 在 SQL Server 中创建数据仓库各层数据库
-- ============================================================

USE master;
GO

-- ----------------------------------------------------------
-- 1. 业务系统数据库(OLTP 源系统,演示用)
-- ----------------------------------------------------------
CREATE DATABASE business_db;
GO

-- ----------------------------------------------------------
-- 2. PSA 层数据库(Persistent Staging Area,持久化暂存区)
--    直接接收源系统数据,保留完整历史
-- ----------------------------------------------------------
CREATE DATABASE psa_db;
GO

-- ----------------------------------------------------------
-- 4. Star Schema 层数据库(维度建模层)
--    事实表 + 维度表
-- ----------------------------------------------------------
CREATE DATABASE star_db;
GO

-- ----------------------------------------------------------
-- 5. Data Mart 层数据库(数据集市层)
--    面向特定业务域的聚合数据
-- ----------------------------------------------------------
CREATE DATABASE mart_db;
GO

-- ----------------------------------------------------------
-- 6. ETL 日志数据库(跨层共享)
-- ----------------------------------------------------------
CREATE DATABASE etl_db;
GO

创建 ETL 日志表

ETL 日志表放在独立数据库中,供所有层共享写入:

USE etl_db;
GO

-- ETL 执行日志表
CREATE TABLE dbo.etl_log (
    log_id          BIGINT IDENTITY(1,1) PRIMARY KEY,
    batch_id        VARCHAR(50)     NOT NULL,
    layer_name      VARCHAR(20)     NOT NULL,   -- psa/dv/star/mart
    db_name         VARCHAR(50)     NOT NULL,   -- 对应的数据库名
    table_name      VARCHAR(100)    NOT NULL,
    start_time      DATETIME        NOT NULL DEFAULT GETDATE(),
    end_time        DATETIME,
    rows_extracted  BIGINT          DEFAULT 0,
    rows_inserted   BIGINT          DEFAULT 0,
    rows_updated    BIGINT          DEFAULT 0,
    rows_rejected   BIGINT          DEFAULT 0,
    status          VARCHAR(20)     DEFAULT 'RUNNING',  -- RUNNING/SUCCESS/FAILED
    error_message   NVARCHAR(MAX),
    created_at      DATETIME        DEFAULT GETDATE()
);
GO

-- 创建索引
CREATE NONCLUSTERED INDEX idx_etl_log_batch
    ON dbo.etl_log(batch_id);
CREATE NONCLUSTERED INDEX idx_etl_log_status
    ON dbo.etl_log(status);
CREATE NONCLUSTERED INDEX idx_etl_log_layer
    ON dbo.etl_log(layer_name);
GO

创建公共工具函数

工具函数放在 etl_db 中,供各层 ETL 调用:

USE etl_db;
GO

-- ============================================================
-- 获取当前 ETL 批次时间戳
-- ============================================================
CREATE FUNCTION dbo.get_etl_timestamp()
RETURNS DATETIME
AS
BEGIN
    RETURN GETDATE();
END;
GO

-- ============================================================
-- 生成 Hash Key(用于业务键哈希)
-- 输入:业务键文本
-- 输出:32 位 MD5 哈希字符串(大写)
-- ============================================================
CREATE FUNCTION dbo.generate_hash_key(@input_text NVARCHAR(MAX))
RETURNS VARCHAR(32)
AS
BEGIN
    DECLARE @result VARCHAR(32);
    SET @result = SUBSTRING(
        CONVERT(VARCHAR(32), HASHBYTES('MD5', UPPER(LTRIM(RTRIM(ISNULL(@input_text, N'NULL'))))), 2),
        1, 32
    );
    RETURN @result;
END;
GO

-- ============================================================
-- 生成复合 Hash Key(用于差异检测)
-- 输入:以 '||' 分隔的多个字段拼接字符串
-- 输出:32 位 MD5 哈希字符串(大写)
-- ============================================================
CREATE FUNCTION dbo.generate_composite_hash(@combined_text NVARCHAR(MAX))
RETURNS VARCHAR(32)
AS
BEGIN
    DECLARE @result VARCHAR(32);
    SET @result = SUBSTRING(
        CONVERT(VARCHAR(32), HASHBYTES('MD5', UPPER(LTRIM(RTRIM(ISNULL(@combined_text, N'NULL'))))), 2),
        1, 32
    );
    RETURN @result;
END;
GO

-- ============================================================
-- 生成日期键(YYYYMMDD 整数格式,用于维度表)
-- ============================================================
CREATE FUNCTION dbo.generate_date_key(@input_date DATE)
RETURNS INT
AS
BEGIN
    RETURN YEAR(@input_date) * 10000 + MONTH(@input_date) * 100 + DAY(@input_date);
END;
GO

验证环境

-- ============================================================
-- 验证所有数据库已创建
-- ============================================================
USE master;
GO

SELECT
    name            AS database_name,
    database_id,
    create_date,
    state_desc      AS state
FROM sys.databases
WHERE name IN (
    N'business_db',
    N'psa_db',
    N'dv_db',
    N'star_db',
    N'mart_db',
    N'etl_db'
)
ORDER BY name;
GO

-- ============================================================
-- 测试工具函数
-- ============================================================
USE etl_db;
GO

-- 测试 Hash Key 生成
SELECT etl_db.dbo.generate_hash_key(N'CUSTOMER-001')    AS customer_hash;
SELECT etl_db.dbo.generate_composite_hash(N'C001||P001||2024-01-15') AS composite_hash;

-- 测试日期键生成
SELECT etl_db.dbo.generate_date_key('2024-01-15')       AS date_key;  -- 返回 20240115

-- 测试时间戳函数
SELECT etl_db.dbo.get_etl_timestamp()                   AS etl_ts;
GO

跨库引用说明

在 SQL Server 中,跨库访问使用 三段式 命名:

[数据库名].[schema名].[对象名]

本教程中的常用跨库引用示例:

-- 从业务库抽取数据到 PSA 层(直接抽取)
INSERT INTO psa_db.dbo.orders (...)
SELECT ... FROM business_db.dbo.orders;

-- 从 PSA 层转换到 Data Vault 层
INSERT INTO dv_db.dbo.hub_customer (...)
SELECT ... FROM psa_db.dbo.customers;

-- 从 Data Vault 层构建 Star Schema
INSERT INTO star_db.dbo.fact_order (...)
SELECT ... FROM dv_db.dbo.hub_customer h
JOIN dv_db.dbo.sat_customer s ON h.hub_customer_key = s.hub_customer_key;

-- 从 Star Schema 聚合到 Data Mart
INSERT INTO mart_db.dbo.sales_summary (...)
SELECT ... FROM star_db.dbo.fact_order f
JOIN star_db.dbo.dim_date d ON f.order_date_key = d.date_key;

注意:跨库引用要求所有数据库在同一 SQL Server 实例下。如需跨实例访问,需配置链接服务器(Linked Server)


数据仓库分层架构速查

┌─────────────────────────────────────────────────────────────────────┐
│                        数据仓库分层架构                               │
│                                                                     │
│  business_db          OLTP 业务系统(演示用源系统)                    │
│  │  orders, customers, products                                     │
│  │                                                                  │
│  ↓ Extract(直接抽取到 PSA)                                          │
│  │                                                                  │
│  psa_db               PSA 层 —— 持久化暂存,保留全部历史               │
│  │  orders, customers, products + 版本控制字段                       │
│  │                                                                  │
│  ↓ Transform(Fact & Dim 建模)                                      │
│  │                                                                 │
│  star_db              Star Schema 层 —— 维度模型                     │
│  │  fact_order, dim_customer, dim_product, dim_date...              │
│  │                                                                  │
│  ↓ Aggregate(按业务域聚合)                                          │
│  │                                                                  │
│  mart_db              Data Mart 层 —— 数据集市                        │
│     sales_summary, customer_rfm, finance_report...                  │
│                                                                     │
│  etl_db               ETL 日志库(跨层共享)                           │
│     etl_log, 工具函数                                                │
└─────────────────────────────────────────────────────────────────────┘

小结

概念 要点
数据仓库定义 面向主题、集成、非易失、时变
与 OLTP 区别 分析 vs 操作,历史 vs 当前,大查询 vs 小事务
历史演进 1988年提出 → 1990s成熟 → 2000s工具化 → 2010s云化
核心价值 统一口径、历史保存、性能隔离、决策支持
分库架构 business_db → psa_db → dv_db → star_db → mart_db
跨库引用 database.dbo.table 三段式命名
ETL 日志 独立 etl_db,所有层共享写入
工具函数 etl_db.dbo.generate_hash_key / generate_composite_hash / generate_date_key

特殊说明

数据仓库的方法论,大方向都差不多,但是实现细节以及各个地方的叫法并不是非常的统一,这个系列是以我个人的经验总结配合AI的整理而成,如果您遇到的方法论有所不同,也欢迎在这里进行分享。