概念 | 定义 | 技术实现 | 示例 |
---|---|---|---|
代理键 | 自增主键,解耦业务与数据存储 | 序列生成器/UUID | customer_sk |
退化维度 | 直接存储在事实表的业务键 | 冗余存储关键属性 | order_id |
微型维度 | 将高频变化的属性单独建模 | 独立维度表+外键关联 | 用户行为评分 |
桥接表 | 解决多值维度关联问题 | 建立关系映射表 | 用户标签关联表 |
-- 业务过程注册表
CREATE TABLE business_process (
process_id INT PRIMARY KEY,
process_name VARCHAR(50) COMMENT '流程名称',
fact_table VARCHAR(50) COMMENT '对应事实表',
description VARCHAR(200) COMMENT '业务描述'
);
INSERT INTO business_process VALUES
(1, '用户下单', 'fact_orders', '从加入购物车到提交订单的全流程'),
(2, '支付成功', 'fact_payments', '从支付发起至到账确认的完整过程');
错误示范:按小时聚合订单金额(丢失明细)
正确实践:
CREATE TABLE fact_order_items (
order_item_id BIGINT COMMENT '订单项唯一标识',
order_time TIMESTAMP COMMENT '精确到毫秒的时间戳',
product_sk INT COMMENT '商品代理键',
user_sk INT COMMENT '用户代理键',
quantity SMALLINT COMMENT '购买数量',
unit_price DECIMAL(10,2) COMMENT '商品单价',
total_price DECIMAL(12,2) COMMENT '总金额=单价*数量',
dt DATE COMMENT '分区日期'
) PARTITIONED BY (dt)
STORED AS ORC
TBLPROPERTIES ("orc.compress"="ZLIB");
CREATE TABLE dim_date (
date_key INT PRIMARY KEY,
calendar_date DATE,
fiscal_year SMALLINT COMMENT '财年(4月1日起)',
fiscal_quarter TINYINT,
week_of_year TINYINT,
is_workday BOOLEAN,
holiday_type VARCHAR(20)
COMMENT '日期维度表';
-- 财年计算逻辑
UPDATE dim_date
SET fiscal_year = CASE
WHEN MONTH(calendar_date) >= 4 THEN YEAR(calendar_date)
ELSE YEAR(calendar_date) - 1
END;
CREATE TABLE dim_customer_scd2 (
customer_sk INT PRIMARY KEY,
customer_id VARCHAR(20),
name VARCHAR(100),
address VARCHAR(200),
start_date DATE,
end_date DATE DEFAULT '9999-12-31',
is_current BOOLEAN
) USING HUDI
TBLPROPERTIES (
'primaryKey' = 'customer_sk',
'preCombineField' = 'start_date'
);
MERGE INTO dim_customer_scd2 AS target
USING (
SELECT
customer_id,
name,
address,
effective_date
FROM ods_customer_updates
) AS source
ON target.customer_id = source.customer_id
AND target.is_current = true
WHEN MATCHED THEN
UPDATE SET
end_date = source.effective_date - INTERVAL 1 DAY,
is_current = false
WHEN NOT MATCHED THEN
INSERT (customer_sk, customer_id, name, address, start_date, is_current)
VALUES (NEXTVAL('customer_sk_seq'), source.customer_id,
source.name, source.address, source.effective_date, true);
类型 | 特点 | 刷新策略 | 示例 |
---|---|---|---|
事务事实表 | 记录原子业务事件 | 实时/准实时 | 订单支付事件 |
周期快照表 | 定期状态记录 | 每日/每月 | 日终账户余额 |
累积快照表 | 跟踪多阶段流程 | 事件触发更新 | 订单全生命周期状态 |
-- 累积快照表示例(物流跟踪)
CREATE TABLE fact_order_fulfillment (
order_sk INT,
create_date_sk INT,
pay_date_sk INT,
ship_date_sk INT,
receive_date_sk INT,
status VARCHAR(20)
COMMENT '订单履约生命周期表';
分析主题 | 核心维度 | 关键指标 | 分析目标 |
---|---|---|---|
用户价值分层 | 时间+RFM属性 | 消费金额、频次、最近购买日 | 客户群体细分与精准营销 |
商品关联销售 | 商品+用户画像 | 购物篮分析、关联规则 | 交叉销售策略优化 |
渠道转化分析 | 流量来源+设备类型 | 转化率、跳出率、会话时长 | 渠道效果评估与预算分配 |
-- RFM宽表(预聚合)
CREATE MATERIALIZED VIEW agg_user_rfm
AS SELECT
user_sk,
MAX(date_key) AS last_purchase_date,
COUNT(order_sk) AS frequency,
SUM(amount) AS monetary
FROM fact_orders
GROUP BY user_sk
PARTITIONED BY (user_sk % 10);
-- 用户标签桥接表
CREATE TABLE bridge_user_tags (
user_sk INT,
tag_id INT,
relevance DECIMAL(3,2)
) COMMENT '用户-标签多对多关系';
-- 使用案例:高消费母婴用户
SELECT
u.user_sk,
SUM(o.amount) AS total_spent
FROM fact_orders o
JOIN bridge_user_tags t ON o.user_sk = t.user_sk
WHERE t.tag_id IN (115, 209) -- 母婴+高消费标签
GROUP BY u.user_sk
HAVING total_spent > 5000;
场景 | 优化方案 | 技术实现 |
---|---|---|
宽表查询 | 列式存储+向量化执行 | Apache Arrow格式 |
实时维度更新 | 异步Compaction策略 | Hudi MOR表 |
历史数据分析 | Z-Order聚类存储 | 按时间+品类双重排序 |
-- Hudi表优化配置
CREATE TABLE fact_orders_hudi (...)
USING HUDI
TBLPROPERTIES (
'hoodie.compact.inline' = 'true',
'hoodie.compact.inline.max.delta.commits' = '20',
'hoodie.parquet.max.file.size' = '134217728' -- 128MB
);
-- ClickHouse物化视图
CREATE MATERIALIZED VIEW agg_daily_sales
ENGINE = SummingMergeTree
ORDER BY (date, product_id)
AS SELECT
toDate(order_time) AS date,
product_id,
sum(total_price) AS sales
FROM fact_orders
GROUP BY date, product_id;
随堂测验
习题解析
下期预告:《DW和BI架构》
互动话题:你在学习SQL时遇到过哪些坑?欢迎评论区留言讨论!
️温馨提示:我是[随缘而动,随遇而安], 一个喜欢用生活案例讲技术的开发者。如果觉得有帮助,点赞关注不迷路