在原生编译存储过程中使用非内存优化表(无需自定义表类型)
能否在不转换为内存优化表的前提下创建原生编译存储过程?
答案是可以,但有几个关键前提和限制,主要取决于你使用的SQL Server版本以及查询的隔离级别设置:
版本要求:这个特性从SQL Server 2016(及后续版本,包括Azure SQL Database)开始支持。如果你用的是SQL Server 2014,那原生编译存储过程只能访问内存优化表,无法直接引用磁盘上的普通表和视图。
隔离级别规则:原生编译存储过程默认使用
SNAPSHOT隔离级别,要访问磁盘表/视图,你需要满足以下其中一种条件:- 在查询磁盘表或视图时,显式添加隔离级别提示:
- 使用
WITH (SNAPSHOT):这要求目标磁盘表已经开启ALLOW_SNAPSHOT_ISOLATION选项(可以通过ALTER TABLE [TableName] SET ALLOW_SNAPSHOT_ISOLATION ON;设置); - 使用
WITH (NOLOCK)(对应READ UNCOMMITTED隔离级别):这个不需要额外配置磁盘表,但会读取未提交的数据,适合对一致性要求不高的场景。
- 使用
- 在原生编译存储过程的开头设置全局隔离级别为
SNAPSHOT:
同样需要确保所有被访问的磁盘表都开启了SET TRANSACTION ISOLATION LEVEL SNAPSHOT;ALLOW_SNAPSHOT_ISOLATION。
- 在查询磁盘表或视图时,显式添加隔离级别提示:
关于视图的处理:如果视图引用的是普通磁盘表,访问视图时也要遵循上面的隔离级别规则——要么在查询视图时加
WITH (SNAPSHOT)/WITH (NOLOCK)提示,要么存储过程整体设置SNAPSHOT隔离级别并确保视图底层表满足配置要求。额外注意事项:
- 原生编译存储过程本身仍有一些T-SQL语法限制,即使访问磁盘表,也不能使用游标、部分聚合函数或复杂的查询构造;
- 原生编译的性能优势主要体现在内存优化表的访问上,如果你大部分逻辑都依赖磁盘表,改成原生编译可能不会带来明显的性能提升,甚至可能不如普通存储过程,建议先做性能测试再决定是否改造。
内容的提问来源于stack exchange,提问作者Rohith
相关产品推荐
相关产品推荐

