必须用 WITH SCHEMABINDING 创建视图才能建索引,且需满足:两段式表名、显式列名、禁用非确定函数及特定语法;聚集索引键须唯一非空确定;SET ANSI_NULLS/ANSI_PADDING 必须为 ON;查询需匹配视图结构且优化器主动选择。

必须先用 WITH SCHEMABINDING 创建视图
普通视图无法直接加索引,CREATE UNIQUE CLUSTERED INDEX 会报错 “视图未绑定到架构”。关键不是语法写错,而是视图定义没满足前提条件。
常见错误现象:Cannot create index on view 'v_orders' because the view is not schema bound —— 这说明你漏了 WITH SCHEMABINDING,或者建视图时用了 SELECT *、GETDATE() 等被禁止的成分。
- 所有表名必须带两段式名称(如
dbo.Orders),不能只写Orders - 不能出现
SELECT *,所有列必须显式列出 - 禁用非确定性函数:
NEWID()、GETDATE()、CURRENT_TIMESTAMP等都不行 - 不能有子查询、
TOP、UNION、OUTER JOIN、聚合但无GROUP BY等
聚集索引键必须唯一、非空、确定性
索引视图的聚集索引不是随便选一列就能建的。OrderID 行得通,CustomerName 很可能不行——因为后者可能重复、允许 NULL、或来自非主键字段。
实操建议:
- 优先选来源表的主键列(如
Orders.OrderID),确保全局唯一且非空 - 若需按其他字段加速查询(如
CustomerName),可在建好聚集索引后,再加一个NONCLUSTERED索引 - 如果视图含
JOIN,索引键最好覆盖连接列(如CustomerID)和筛选高频列 - 避免用计算列作聚集索引键,除非该列是确定性的(比如
ISNULL(phone, mobile)可以,GETDATE()不行)
SET 选项不匹配会导致索引失效甚至建索引失败
即使视图建好了、索引也创建成功,查询仍可能不走索引视图——根本原因常是会话级 SET 选项不一致。SQL Server 对索引视图要求严格,ANSI_NULLS 和 ANSI_PADDING 必须为 ON,否则优化器直接忽略该索引。
常见错误现象:视图和索引都存在,但执行计划里始终显示“Table Scan”或“Index Scan”原表,而不是“Index Seek”视图索引。
- 建视图前,先运行
SET ANSI_NULLS ON; SET ANSI_PADDING ON; - 检查当前会话值:
SELECT SESSIONPROPERTY('ANSI_NULLS'), SESSIONPROPERTY('ANSI_PADDING') - ODBC/OLE DB 默认是
ON,但 DB-Library 或某些旧客户端默认OFF,容易踩坑 - 不要依赖连接字符串自动设置,显式在脚本开头声明更稳妥
查询不自动命中索引视图的隐藏条件
索引视图不是“建完就生效”的缓存,它依赖查询优化器主动选择。哪怕视图结构完全匹配,以下情况仍可能导致绕过索引视图:
- 查询中用了参数(如
WHERE OrderDate > @date),而索引视图未覆盖该列,或参数类型引发隐式转换 - 外层查询 SELECT 列多于视图定义列,又没加
INCLUDE,触发 Key Lookup 回表,优化器可能放弃使用 - 视图含
GROUP BY时,必须用COUNT_BIG(*)替代COUNT(*),否则无法建索引 - 基表没有主键或唯一约束,或连接列上缺失索引,也会让优化器认为维护成本过高而弃用
最可靠验证方式:打开实际执行计划,看是否出现 Index Seek 或 Index Scan 指向你的视图名;若仍是原表扫描,就得回查定义、SET 选项、查询写法三者是否全部合规。


















