必须加 with schemabinding 才能创建索引视图,否则 create unique clustered index 会报错;加后需两段式表名、禁止 * 和非确定性语法,且仅支持唯一聚集索引,查询须显式使用 with (noexpand) 才生效。

必须加 WITH SCHEMABINDING,否则无法建索引
不加这个选项,视图就只是普通逻辑视图,后续执行 CREATE UNIQUE CLUSTERED INDEX 会直接报错:Cannot create index on view 'xxx' because it is not schema bound.。这不是可选建议,是硬性前提。
加了之后,所有引用的表名必须带两段式命名(如 dbo.customer),不能只写 customer;而且这些表必须和视图在同一个数据库里。一旦加了 SCHEMABINDING,你就不能随意修改基表结构——比如删列、改类型、重命名——除非先删掉索引和视图。
- 视图定义中禁止出现
*,必须显式列出每一列 - 不能用
UNION、INTERSECT、EXCEPT、子查询、TOP、ORDER BY(除非配合TOP)、聚合函数(如COUNT)等非确定性构造 -
SCHEMABINDING会锁住基表的 DDL 权限,部署脚本里要留意执行顺序:先建表 → 再建视图 → 最后建索引
CREATE UNIQUE CLUSTERED INDEX 是唯一允许的索引类型
SQL Server 不允许在视图上建非聚集索引、筛选索引或列存储索引(除非是聚簇列存储,但那属于另一类物化机制)。你只能建一个唯一聚集索引,且索引键必须满足「唯一性 + 非空」——通常选主键列或组合键,比如 customer_id 或 (order_id, order_date)。
如果基表本身没有合适唯一键,得先确认业务逻辑是否允许补全约束,或者加计算列/标识列辅助。强行用 NEWID() 或 ROW_NUMBER() 造唯一键会导致索引不可维护,也违反索引视图的数据一致性要求。
- 索引创建失败常见原因:
SELECT列里有重复值,或某列为NULL但被选作索引键 - 索引键列数不宜过多,一般控制在 2–4 列内;太多会影响写入性能和统计信息精度
- 建完索引后,视图就变成物理存储结构,
sp_spaceused 'view_name'能查到实际占用空间
查询时必须用 WITH (NOEXPAND) 才走索引
这是最容易忽略的一点:即使你建好了索引视图,SQL Server 查询优化器默认仍可能“展开”视图,去扫描底层表,而不是读取已物化的索引数据。结果就是白建了——性能没提升,还多了一层写入开销。
强制走索引的方式只有显式加提示:SELECT * FROM dbo.v_customer_sch_index WITH (NOEXPAND) WHERE Col1 = '998628'。不加这个提示,等于把索引视图当普通视图用。
- 在 SQL Server 2022 中,
NOEXPAND提示仍是必需的;自动识别索引视图的场景极少(仅限极简单查询+特定兼容级别) - 如果视图被嵌套在其他视图或 CTE 中,
NOEXPAND无效,必须拆出来单独引用 - 应用层代码、报表工具生成的 SQL 如果没加这个提示,索引视图就形同虚设
写入性能代价必须提前评估
索引视图不是免费午餐。每次对基表做 INSERT/UPDATE/DELETE,SQL Server 都要同步更新视图的聚集索引页。这意味着:单次写入操作实际触发多次 I/O,尤其当视图涉及多表 JOIN 时,维护成本呈倍数上升。
适合建索引视图的场景很明确:读远多于写(比如报表库、历史归档查询)、查询模式稳定、基表变更频率低(日增
- 测试方法:对比开启前后,相同
INSERT语句的STATISTICS IO和执行时间 - 不要为小表(
- SQL Server 2022 的查询优化器对索引视图的估算仍不够智能,有时会低估
NOEXPAND下的真实开销,务必实测











