物化视图 #

一、物化视图概述 #

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
问题:创建视图后写入变慢

原因:
├── 视图维护开销
├── 视图过多
└── 资源不足

解决:
├── 减少视图数量
├── 优化硬件
└── 考虑异步更新

八、总结 #

物化视图要点:

  1. 自动维护:基表变更自动同步到视图
  2. 主键规则:必须包含基表主键
  3. NULL排除:NULL值不会出现在视图中
  4. 性能开销:影响写入性能
  5. 存储开销:数据冗余
  6. 适用场景:多查询模式、读多写少

下一步,让我们学习高级特性!

最后更新:2026-03-27