课程
物化视图是 SQL 数据库中的一项强大功能,通过将查询结果以物理形式存储在磁盘上,避免反复计算,从而加速查询性能。它们对涉及连接、聚合和大型数据集的复杂、资源密集型查询尤其有用。
在开始之前,建议您学习 DataCamp 的 Introduction to SQL 课程和 SQL Fundamentals 技能路径,掌握 SQL 基础以及如何通过查询提取数据。您还可以参考 SQL Basics Cheat Sheet,了解常用的 SQL 过滤与聚合函数。
什么是 SQL 物化视图?
物化视图是一种特殊的数据库对象,它将查询的结果以物理方式存储,而不是像常规视图那样在访问时即时计算。常规 SQL 视图是一个已保存的 SQL 查询,每次访问都会动态生成结果;而物化视图会预计算并将数据存储为类似表的结构。
通过将结果集存储到磁盘,物化视图可以显著降低数据库负载、提升查询性能,并有助于简化计算密集型操作的处理。
在 SQL 中创建物化视图
创建物化视图需要使用 CREATE MATERIALIZED VIEW 语法,不同 SQL 数据库的语法略有差异。以下展示在 SQL Server、PostgreSQL 和 Oracle 中创建物化视图的方法。
PostgreSQL 中的物化视图
在 PostgreSQL 中,您可以使用如下语法创建物化视图。此示例创建名为 sales_summary 的物化视图,用于汇总各产品的总销量与总收入。
-- Create a materialized view to summarize sales data
CREATE MATERIALIZED VIEW sales_summary AS
SELECT product_id,
SUM(quantity) AS total_quantity,
SUM(price * quantity) AS total_revenue
FROM sales
GROUP BY product_id;
SQL Server 中的物化视图
在 SQL Server 中,物化视图称为“索引视图”(Indexed Views)。要创建索引视图,底层表需满足特定要求,例如启用 WITH SCHEMABINDING 选项。
WITH SCHEMABINDING 选项可确保在索引视图存在期间架构不会变更。要将视图物化,必须为其创建唯一聚集索引。
-- Create an indexed view with schema binding to summarize sales data
CREATE VIEW sales_summary
WITH SCHEMABINDING
AS
SELECT product_id,
COUNT_BIG(*) AS record_count,
SUM(ISNULL(quantity, 0)) AS total_quantity,
SUM(ISNULL(price, 0) * ISNULL(quantity, 0)) AS total_revenue
FROM sales
GROUP BY product_id;
GO
-- Create a unique clustered index to materialize the view
CREATE UNIQUE CLUSTERED INDEX IX_sales_summary
ON sales_summary (product_id);
GO
如果您想进一步了解 SQL Server,建议查看我们的 SQL Server Fundamentals 技能路径,熟悉用于数据分析的多种 SQL 技能。
Oracle 中的物化视图
在 Oracle 中创建物化视图的语法与 PostgreSQL 类似。我们还可以指定刷新选项,例如 ON DEMAND 或 ON COMMIT。
-- Create a materialized view to summarize sales data
CREATE MATERIALIZED VIEW sales_summary
BUILD IMMEDIATE
REFRESH FAST ON DEMAND
AS
SELECT product_id, SUM(quantity) AS total_quantity, SUM(price * quantity) AS total_revenue
FROM sales
GROUP BY product_id;
分布式数据库中的物化视图
在支持分布式数据仓库的数据库(如 Azure Synapse 或 Amazon Redshift)中,物化视图还可以指定分布方式以获得更好的性能。
Amazon Redshift 的哈希分布
下面的查询创建名为 sales_summary 的物化视图,按 product_id 汇总总销量与总收入。DISTSTYLE KEY 和 DISTKEY(product_id) 选项确保数据基于 product_id 在各节点间分布,从而提升在该列上进行连接查询时的性能。
-- Create a materialized view with key-based distribution for efficient joins
CREATE MATERIALIZED VIEW sales_summary
DISTSTYLE KEY
DISTKEY(product_id)
AS
SELECT product_id,
SUM(quantity) AS total_quantity,
SUM(price * quantity) AS total_revenue
FROM sales
GROUP BY product_id;
Azure Synapse 的轮询分布
此查询创建名为 sales_summary 的物化视图,按 product_id 汇总总销量与总收入。ROUND_ROBIN 分布会将数据平均分布到各节点,适用于不严重依赖连接的场景。
-- Create a materialized view with round-robin distribution for balanced data storage
CREATE MATERIALIZED VIEW sales_summary
WITH (DISTRIBUTION = ROUND_ROBIN)
AS
SELECT product_id,
SUM(quantity) AS total_quantity,
SUM(price * quantity) AS total_revenue
FROM sales
GROUP BY product_id;在 SQL 中刷新物化视图
物化视图中的数据可以刷新,以与底层表保持同步。选择何种刷新方式取决于具体数据库的业务需求与性能考量。下面介绍物化视图的常见数据刷新方法。
手动刷新
手动刷新仅在用户明确发起时才会执行刷新。该方式能最大程度控制数据更新时机,适用于数据变更不频繁或在离峰时段进行更新的场景。
以下查询展示了在 PostgreSQL 中的手动刷新方法。
REFRESH MATERIALIZED VIEW sales_summary;
定期刷新
在指定的刷新周期内,物化视图会按预设间隔自动刷新,无需用户干预即可确保数据较为最新。此方法适用于对时效性有要求且需要保持数据相对实时的应用。
下面的示例展示了如何在 Oracle 中通过在 CREATE MATERIALIZED VIEW 语句中直接定义刷新计划来实现定期刷新。刷新时间设置为每小时一次。
-- Create a materialized view to aggregate sales data
-- Set to refresh completely every hour
CREATE MATERIALIZED VIEW sales_summary
REFRESH COMPLETE START WITH (SYSDATE) NEXT (SYSDATE + 1/24)
AS
SELECT product_id,
SUM(quantity) AS total_quantity,
SUM(price * quantity) AS total_revenue
FROM sales
GROUP BY product_id;
按需刷新
按需刷新在底层数据发生变化时触发,通常通过触发器机制实现。这样可以确保物化视图始终包含最新数据。例如,在 PostgreSQL 中,可以设置触发器在底层表发生变更时刷新视图。
完全刷新与增量刷新
在物化视图中可以选择完全刷新或增量刷新。下表总结了两种方法及其适用场景。
| 刷新类型 | 说明 | 优势 | 不足 |
|---|---|---|---|
| 完全刷新 | 重新加载整个数据集,替换视图中的所有现有数据 | - 实现简单 - 重建整个视图 |
- 对大型数据集资源消耗大 - 刷新时间更长 |
| 增量刷新 | 仅更新视图中发生变化的部分 | - 更高效,仅处理已修改数据 - 适用于频繁变更的大型数据集 |
- 需要额外配置(如用于跟踪变更的日志) - 并非所有查询都支持 |
物化视图的最佳实践
使用物化视图时,请考虑以下实践以实现最佳效果。
- 选择合适的查询进行物化:优先物化复杂且资源密集的查询,如连接、聚合和子查询。这类查询受益于预计算结果,可降低数据库负载。
- 平衡数据新鲜度与性能:根据您的使用场景选择合适的刷新策略,如手动、定期或按需刷新。尽可能使用增量刷新以降低计算开销,并根据数据变更频率设置刷新间隔。
- 用物化视图优化查询密集型工作负载:在需要快速响应的 BI 报表与仪表板中充分利用物化视图。您也可以为物化视图中使用的列建立索引,以加速过滤与排序。
不同数据库系统中的物化视图
如您所见,不同数据库系统对物化视图的支持程度各不相同。下表总结了这些数据库中物化视图的特色功能与限制。
| 数据库系统 | 刷新方式 | 增量刷新 | 自动刷新 | 特性/限制 |
|---|---|---|---|---|
| PostgreSQL | 手动(REFRESH MATERIALIZED VIEW) | 否 | 否 | 缺乏原生增量刷新。需要手动调度。 |
| SQL Server | 自动(索引视图) | 是(自动同步) | 是 |
需要 |
| Oracle | 手动、提交时、计划任务 | 是(快速刷新) | 是 | 支持快速刷新、分区与并行。需要视图日志。 |
| Amazon Redshift | 手动、计划任务 | 是 | 是 | 支持使用哈希或轮询分布的分布式数据。 |
| MySQL | 无原生支持 | 否 | 否 | 需要替代方案(如临时表、第三方工具)。 |
| Azure Synapse | 手动、计划任务 | 是 | 是 | 可选择不同分布策略进行优化。 |
如果您常用 SQL Server,建议学习 DataCamp 的 Introduction to SQL Server 课程,掌握用于数据分析的 Microsoft SQL Server 基础;同时查看我们的 SQL Server Developer 职业路径,了解如何优化查询并排查 SQL Server 中的问题。
其他注意事项
尽管 SQL 物化视图有助于优化查询,它们也存在一些挑战与限制。以下是物化视图的常见问题及应对方法。
- 存储开销:物化视图将查询结果以物理形式存储在磁盘上,会增加存储需求。为避免不必要的存储占用,仅对资源密集型查询进行物化,并对大型数据集的物化视图进行分区。
- 更新成本与刷新开销:保持物化视图与底层表同步可能较为耗费资源,尤其当视图需要频繁更新或涉及复杂计算时。为降低刷新开销,在支持的情况下使用增量刷新,或在数据库负载较低的时段设置合适的刷新间隔。
- 数据一致性与同步:如果底层数据频繁变化,物化视图可能会过期,导致数据陈旧。为避免此问题,应选择合适的刷新策略,并监控数据变更以按需调整刷新策略。
- 维护开销:物化视图需要持续维护,例如设置合适的刷新计划、监控存储使用情况以及跟踪对底层表的依赖。为应对这一挑战,请使用自动化刷新计划、监控系统性能,并为刷新失败设置告警。
结论
在 SQL 数据库中,物化视图是优化查询性能的有力工具。它们将查询结果以物理形式存储,借助减少重复计算来加速查询。这使其非常适合处理涉及连接、聚合和大型数据集的复杂、资源密集型查询。了解如何在不同数据库中实现物化视图,将有助于提升您的查询与数据库优化能力。
如果您希望提升 SQL 技能,建议尝试 DataCamp 的 Associate Data Analyst in SQL 职业路径,成为一名熟练的数据分析师。Reporting in SQL 课程也将帮助您熟练构建复杂报表与仪表板,以高效呈现数据。最后,获取 SQL Associate Certification 认证,展示您运用 SQL 解决业务问题的能力,从而在众多专业人士中脱颖而出。
数据科学技术写作者,具备数据分析、商业智能和数据科学的一线实践经验。我撰写以行业为导向的实用内容,涵盖 SQL、Python、Power BI、Databricks 和数据工程,并以真实的分析工作为基础。我的写作兼顾技术深度与业务影响,帮助专业人士将数据转化为自信的决策。
常见问答
SQL 中什么是物化视图?
物化视图是一种数据库对象,会将查询结果以物理形式存储,从而通过避免重复计算来优化性能。
物化视图与常规视图有何不同?
与每次访问都会动态检索数据的常规视图不同,物化视图将数据存储为物理表,从而实现更快的查询执行。
完全刷新与增量刷新有何区别?
完全刷新会重新计算整个视图;增量刷新仅更新发生变化的数据,从而提升效率。
哪些数据库支持物化视图?
PostgreSQL、SQL Server(索引视图)、Oracle、Amazon Redshift 和 Azure Synapse Analytics 支持物化视图,且各自具有不同特性与限制;MySQL 缺乏原生支持。
物化视图是否会占用额外存储?
是的,由于以物理形式存储数据,物化视图会增加存储需求。
