索引视图能加速统计类查询,因其将聚合、分组等预计算结果物化并持久化到磁盘,查询时直接读取索引页而无需重复扫描基表和计算。

为什么索引视图在 SQL Server 2019 中能加速统计类查询
因为索引视图(Indexed View)本质是物化了的查询结果,SQL Server 把 SELECT 的计算结果持久化到磁盘,并在其上建立唯一聚集索引——这意味着对视图的聚合、分组、连接等预计算结果可以直接被查询优化器复用,无需每次执行时重跑逻辑。尤其适合频繁执行的统计类查询(如 SUM/COUNT/AVG 按维度分组),避免反复扫描基表和重复聚合。
但注意:不是所有视图都能加索引。SQL Server 强制要求必须满足一系列“可索引性”条件,否则 CREATE UNIQUE CLUSTERED INDEX 会直接报错。
创建索引视图前必须满足的硬性条件
以下任一不满足,CREATE INDEX 就会失败,且错误信息往往不直观(比如只提示“无法为视图创建索引”):
- 视图定义中必须包含
SCHEMABINDING,且所有引用的基表都需用两段式命名(schema.table) - 必须使用唯一聚集索引,且索引键必须覆盖所有参与分组/聚合的列(例如
GROUP BY a, b,则索引键至少含a, b) - 不能含
GETDATE()、NEWID()、子查询、外联接、TOP、UNION等非确定性或不可持久化结构 - 如果含聚合函数(
SUM、COUNT_BIG等),必须显式指定COUNT_BIG(*)而非COUNT(*),否则建索引失败 - 数据库选项
ANSI_NULLS和QUOTED_IDENTIFIER必须为ON(SSMS 新建查询默认开启,但通过某些 ORM 或旧脚本可能关闭)
一个能真正生效的统计类索引视图示例
假设你常查「每个部门的员工数和平均薪资」,基表为 dbo.Employees,字段含 DeptId、Salary:
CREATE VIEW dbo.v_DepartmentStats
WITH SCHEMABINDING
AS
SELECT
DeptId,
COUNT_BIG(*) AS EmpCount,
AVG(Salary) AS AvgSalary
FROM dbo.Employees
GROUP BY DeptId;
GO
<p>-- 必须先建唯一聚集索引,否则视图仍是虚拟的
CREATE UNIQUE CLUSTERED INDEX IX_v_DepartmentStats_DeptId
ON dbo.v_DepartmentStats (DeptId);
之后执行 SELECT DeptId, EmpCount FROM dbo.v_DepartmentStats WHERE DeptId = 123,执行计划会显示直接读取索引叶子节点,完全跳过基表扫描。但注意:若查询里加了 WHERE Salary > 5000 这种未出现在视图定义里的过滤条件,优化器大概率不会使用该索引视图。
容易被忽略的维护成本和适用边界
索引视图不是“设好就一劳永逸”的加速器。它把统计计算从查询时移到了写入时:
- 每次对
Employees执行INSERT/UPDATE/DELETE,SQL Server 都要同步更新v_DepartmentStats的索引页——写入延迟上升,事务日志增长更快 - 视图定义变更(如加一列)必须先
DROP INDEX再DROP VIEW,不能ALTER VIEW - 只有查询文本与视图定义**完全匹配或可被自动匹配**时,优化器才考虑使用它;启用
NOEXPAND提示可强制走索引视图,但会失去查询重写优化机会 - 在 SQL Server Standard Edition 中,索引视图仅对查询中**显式引用该视图名**生效;Enterprise Edition 支持自动匹配(即查基表时也可能悄悄用上)
真正值得建索引视图的场景很窄:统计逻辑固定、查询频次极高、基表写入压力可控、且结果集远小于原始数据量——比如按天汇总的销售报表视图,每天只刷一次,但被 BI 工具每分钟轮询十几次。

















