必须先用WITH SCHEMABINDING创建合规聚合视图并满足所有索引视图前提(如COUNT_BIG(*)、GROUP BY覆盖关键列、基表有主键等),再建唯一聚集索引;否则因视图未绑定架构或不满足硬性要求而报错。

不能直接为含聚合的普通视图建唯一聚集索引;必须先用 WITH SCHEMABINDING 创建合规的索引视图,再建 UNIQUE CLUSTERED INDEX,否则必然失败。
为什么 CREATE UNIQUE CLUSTERED INDEX 在聚合视图上总报错?
常见错误提示如:Cannot create index on view 'vw_SalesSummary' because the view is not schema bound 或更长的“不满足索引视图要求”。根本原因不是语法写错,而是视图定义本身没过 SQL Server 的硬性校验关。
- 视图未用
WITH SCHEMABINDING创建(这是强制前提) -
SELECT列里用了*、GETDATE()、NEWID()、子查询或TOP - 用了
COUNT(*)而非COUNT_BIG(*)(聚合视图中必须用后者) - 缺少
GROUP BY,或GROUP BY列不覆盖所有连接/筛选关键列 - 基表没有主键或唯一非空约束(尤其用于
GROUP BY的列)
创建可索引聚合视图的最小合规写法
以统计每个产品的订单总数和销售总额为例,以下结构是能成功建索引的底线:
CREATE VIEW dbo.vw_SalesSummary
WITH SCHEMABINDING
AS
SELECT
ProductID,
COUNT_BIG(*) AS TotalOrders,
SUM(Quantity) AS TotalQuantity,
SUM(Quantity * UnitPrice) AS TotalRevenue
FROM dbo.Sales
GROUP BY ProductID;注意这几点:
-
ProductID必须是dbo.Sales表的主键或有唯一非空约束 - 必须用
COUNT_BIG(*),不能用COUNT(*) - 所有列名都带两段式前缀(
dbo.Sales),不能省略 schema - 不能在
SELECT中加计算列如ISNULL(UnitPrice, 0),除非该函数是确定性的
建完索引后,查询怎么才能真正用上它?
索引视图不会自动被所有查询命中,尤其在 Standard / Express 版本中:
- 在 Enterprise / Developer 版本中,查询优化器可能自动匹配并使用它(即使没显式引用视图名)
- 在其他版本中,必须显式引用视图,并加
WITH (NOEXPAND)提示,例如:SELECT * FROM dbo.vw_SalesSummary WITH (NOEXPAND) WHERE ProductID = 123 - 如果外部查询加了
ORDER BY或WHERE条件,但视图定义里没包含对应索引列,仍可能退化为扫描基表 - 执行计划里看到
Clustered Index Scan或Index Seek对应的是视图索引,而不是Table Scan或Hash Match基表操作,才算真正生效
聚合视图的维护成本常被低估
它不是“一劳永逸”的加速器。每次对基表 INSERT/UPDATE/DELETE,SQL Server 都要同步更新视图的物理存储 —— 这会拖慢写操作,且占用额外磁盘空间。尤其当 GROUP BY 维度多、基数高(比如按日期+地区+产品三级分组),索引体积和维护开销会迅速上升。读多写少、结果集相对稳定(如日报汇总、客户等级统计)才是它真正适用的场景。


















