物化视图 #
一、物化视图概述 #
1.1 什么是物化视图 #
物化视图是基于基表自动维护的预计算数据副本。
text
物化视图工作原理:
基表
┌─────────────────────────────────────────────────────────┐
│ user_id(PK) │ name │ email │ age │
├─────────────────────────────────────────────────────────┤
│ uuid-001 │ 张三 │ zhang@example.com │ 28 │
│ uuid-002 │ 李四 │ li@example.com │ 32 │
└─────────────────────────────────────────────────────────┘
物化视图(按email查询)
┌─────────────────────────────────────────────────────────┐
│ email(PK) │ user_id(CK) │ name │ age │
├─────────────────────────────────────────────────────────┤
│ li@example.com │ uuid-002 │ 李四 │ 32 │
│ zhang@example.com│ uuid-001 │ 张三 │ 28 │
└─────────────────────────────────────────────────────────┘
自动同步:基表数据变更时,视图自动更新
1.2 物化视图特点 #
text
物化视图特点:
优点
├── 自动维护
├── 支持不同查询模式
├── 查询性能高
└── 数据一致性强
限制
├── 写入性能开销
├── 视图主键必须包含基表主键
├── 不能更新视图
└── 存储开销
二、创建物化视图 #
2.1 基本语法 #
sql
CREATE MATERIALIZED VIEW [IF NOT EXISTS] view_name AS
SELECT column_name [, ...]
FROM table_name
WHERE column_name IS NOT NULL [AND column_name IS NOT NULL ...]
PRIMARY KEY (column_name, column_name [, ...])
[WITH table_options];
2.2 基本示例 #
sql
-- 基表
CREATE TABLE users (
user_id UUID PRIMARY KEY,
name TEXT,
email TEXT,
age INT
);
-- 创建物化视图(按email查询)
CREATE MATERIALIZED VIEW users_by_email AS
SELECT user_id, name, email, age
FROM users
WHERE email IS NOT NULL AND user_id IS NOT NULL
PRIMARY KEY (email, user_id);
-- 创建物化视图(按name查询)
CREATE MATERIALIZED VIEW users_by_name AS
SELECT user_id, name, email, age
FROM users
WHERE name IS NOT NULL AND user_id IS NOT NULL
PRIMARY KEY (name, user_id);
2.3 主键规则 #
text
物化视图主键规则:
必须包含
├── 基表的所有主键列
└── 作为分区键的非空列
规则
├── 视图主键 = 新分区键 + 基表主键
├── 新分区键必须有NOT NULL条件
└── 保证每行唯一
示例:
基表 PRIMARY KEY (user_id)
视图 PRIMARY KEY (email, user_id)
└──┬──┘ └───┬───┘
新分区键 基表主键
三、使用物化视图 #
3.1 查询视图 #
sql
-- 按email查询
SELECT * FROM users_by_email
WHERE email = 'zhang@example.com';
-- 按name查询
SELECT * FROM users_by_name
WHERE name = '张三';
-- 范围查询
SELECT * FROM users_by_email
WHERE email >= 'a' AND email < 'z';
3.2 数据同步 #
sql
-- 插入基表数据
INSERT INTO users (user_id, name, email, age)
VALUES (uuid(), '王五', 'wang@example.com', 25);
-- 视图自动更新
SELECT * FROM users_by_email WHERE email = 'wang@example.com';
-- 返回新插入的数据
-- 更新基表数据
UPDATE users SET email = 'wang_new@example.com'
WHERE user_id = ?;
-- 视图自动同步
SELECT * FROM users_by_email WHERE email = 'wang_new@example.com';
-- 返回更新后的数据
四、视图限制 #
4.1 主键限制 #
sql
-- 错误:缺少基表主键
CREATE MATERIALIZED VIEW bad_view AS
SELECT user_id, email
FROM users
WHERE email IS NOT NULL
PRIMARY KEY (email);
-- 错误:必须包含基表主键user_id
-- 正确
CREATE MATERIALIZED VIEW good_view AS
SELECT user_id, email
FROM users
WHERE email IS NOT NULL AND user_id IS NOT NULL
PRIMARY KEY (email, user_id);
4.2 NULL处理 #
sql
-- NULL值不会出现在视图中
INSERT INTO users (user_id, name) VALUES (uuid(), '无名');
-- 视图中没有这条记录(email为NULL)
SELECT * FROM users_by_email WHERE email = ?;
-- 返回空结果
4.3 性能开销 #
text
性能开销:
写入
├── 每个视图增加写入开销
├── 视图越多,写入越慢
└── 需要权衡查询和写入
存储
├── 视图占用额外存储
├── 数据冗余
└── 需要考虑存储成本
五、管理物化视图 #
5.1 查看视图 #
sql
-- 列出所有视图
DESCRIBE MATERIALIZED VIEWS;
-- 查看特定视图
DESCRIBE MATERIALIZED VIEW users_by_email;
5.2 删除视图 #
sql
-- 删除视图
DROP MATERIALIZED VIEW users_by_email;
-- 使用IF EXISTS
DROP MATERIALIZED VIEW IF EXISTS users_by_email;
5.3 修改视图 #
sql
-- 不能直接修改视图
-- 需要删除重建
DROP MATERIALIZED VIEW users_by_email;
CREATE MATERIALIZED VIEW users_by_email AS
SELECT user_id, name, email, age, created_at
FROM users
WHERE email IS NOT NULL AND user_id IS NOT NULL
PRIMARY KEY (email, user_id);
六、最佳实践 #
6.1 使用场景 #
text
物化视图适用场景:
适合
├── 多种查询模式
├── 读多写少
├── 需要强一致性
└── 查询性能要求高
不适合
├── 写入频繁
├── 大量视图
├── 数据量大
└── 需要复杂转换
6.2 设计建议 #
text
设计建议:
1. 控制视图数量
└── 每表不超过2-3个视图
2. 选择合适的分区键
└── 高基数、均匀分布
3. 监控性能
└── 关注写入延迟
4. 考虑存储成本
└── 数据冗余开销
6.3 替代方案 #
sql
-- 替代方案:手动维护反范式化表
-- 写入时同时更新两个表
BEGIN BATCH
INSERT INTO users (user_id, name, email)
VALUES (?, ?, ?);
INSERT INTO users_by_email (email, user_id, name)
VALUES (?, ?, ?);
APPLY BATCH;
-- 优点:更灵活的控制
-- 缺点:需要手动维护一致性
七、常见问题 #
7.1 视图数据不一致 #
text
问题:视图数据与基表不一致
原因:
├── 写入失败
├── 网络问题
└── 节点故障
解决:
├── 执行repair
├── 重建视图
└── 检查日志
7.2 写入性能下降 #
text
问题:创建视图后写入变慢
原因:
├── 视图维护开销
├── 视图过多
└── 资源不足
解决:
├── 减少视图数量
├── 优化硬件
└── 考虑异步更新
八、总结 #
物化视图要点:
- 自动维护:基表变更自动同步到视图
- 主键规则:必须包含基表主键
- NULL排除:NULL值不会出现在视图中
- 性能开销:影响写入性能
- 存储开销:数据冗余
- 适用场景:多查询模式、读多写少
下一步,让我们学习高级特性!
最后更新:2026-03-27