必须先用with schemabinding创建视图并满足所有索引视图前提(如两段式表名、无*、无top、count_big替代count等),再创建唯一聚集索引;否则报“视图未绑定到架构”或“不满足索引视图要求”。

不能直接为普通视图创建唯一聚集索引。SQL Server 要求你先将视图定义为“索引视图”(也叫物化视图),且必须满足一整套严格前提条件,否则 CREATE UNIQUE CLUSTERED INDEX 会报错。
为什么 CREATE UNIQUE CLUSTERED INDEX 在视图上失败?
常见错误是执行 CREATE UNIQUE CLUSTERED INDEX idx_v ON dbo.MyView (id) 后收到类似提示:Cannot create index on view 'MyView' because the view is not schema bound. 或更长的“视图不满足索引视图要求”消息。根本原因不是语法写错,而是视图本身未按 SQL Server 的索引视图规范定义。
关键限制包括:
- 视图必须用
SCHEMABINDING创建(即绑定底层表结构,防止被意外修改) - 所有引用的表和函数都必须在同一数据库中,且不能是临时表或表变量
- 视图 SELECT 列中不能含
*、GETDATE()、NEWID()、子查询、聚合函数(除非配合GROUP BY和COUNT_BIG(*))、TOP、UNION、OUTER JOIN等 - 基表必须有主键,且索引键列需覆盖视图中所有用于连接、筛选、分组的列
创建索引视图的最小可行步骤
以一个简单联接视图为例,假设要加速 Orders 和 Customers 的关联查询:
第一步:确认基表有主键 —— Customers.CustomerID 和 Orders.OrderID 必须是主键或至少有唯一非空约束。
第二步:用 SCHEMABINDING 重建视图:
CREATE VIEW dbo.v_OrderCustomer
WITH SCHEMABINDING
AS
SELECT
o.OrderID,
o.OrderDate,
c.CustomerName,
c.City
FROM dbo.Orders AS o
INNER JOIN dbo.Customers AS c ON o.CustomerID = c.CustomerID;
第三步:在视图上建唯一聚集索引(必须唯一、非空、确定性):
CREATE UNIQUE CLUSTERED INDEX IX_v_OrderCustomer_OrderID ON dbo.v_OrderCustomer (OrderID);
注意:OrderID 必须在视图中明确 SELECT 出来,且值全局唯一(通常来自主键)。若想按 CustomerName 查询更快,可额外加非聚集索引,但聚集索引只能有一个。
索引视图生效的前提与陷阱
即使成功建好索引,查询也不一定自动走它 —— SQL Server 优化器默认可能仍选择展开原视图逻辑,尤其当查询含参数、隐式转换或未覆盖全部索引列时。
确保命中索引视图的关键点:
- 查询必须直接引用该视图名,不能嵌套在子查询或 CTE 中(除非启用
EXPAND VIEWS提示) - WHERE 条件中的列最好包含在索引键或包含列中;否则仍可能触发键查找或扫描
- 避免在视图列上做函数操作,例如
WHERE UPPER(CustomerName) = 'ABC'会让索引失效 - 开启
SET ARITHABORT ON(多数客户端默认开启),否则某些连接下索引视图可能被忽略 - 定期更新基表统计信息:
UPDATE STATISTICS dbo.Orders和UPDATE STATISTICS dbo.Customers,否则优化器可能误判成本
什么时候不该用索引视图?
索引视图本质是把计算结果固化到磁盘,换来读性能提升,但代价是写入变慢、存储增加、维护复杂。以下情况应谨慎:
- 基表数据频繁更新(INSERT/UPDATE/DELETE > 100 次/分钟),每次变更都要同步刷新索引视图
- 视图涉及多张大表 JOIN 且其中一张表经常增删字段 ——
SCHEMABINDING会阻止你改表结构 - 业务逻辑常变,导致视图定义需高频迭代,而每次改视图都要先 DROP 所有索引再重建
- 你其实只需要偶尔加速某几个特定查询,此时加覆盖索引比建索引视图更轻量、更灵活
真正值得投入索引视图的场景,通常是那些被高频读取、逻辑稳定、基表写入频率低、且执行计划始终无法有效下推谓词的报表类视图 —— 它不是万能加速器,而是一个需要权衡写入开销的“预计算契约”。










