表和存储过程的本地编译

In-Memory OLTP 引入了本机编译的概念。 SQL Server 可以将访问内存优化表的存储过程本机编译。 SQL Server 还可以本机编译内存优化表。 与解释的 (传统) Transact-SQL 相比,本机编译允许更快的数据访问和更高效的查询执行。 表与存储过程的本地编译生成 DLL。

支持对内存优化表类型进行本机编译。 有关详细信息,请参阅 Memory-Optimized 表变量

本机编译是指将编程构造转换为本机代码的过程,包括处理器指令,无需进一步编译或解释。

In-Memory OLTP 在创建时编译内存优化表,并在加载到本机 DLL 时编译本机存储过程。 此外,在数据库或服务器重启后重新编译 DLL。 重新创建 DLL 所需的信息存储在数据库元数据中。 DLL 不是数据库的一部分,但它们与数据库相关联。 例如,DLL 不包括在数据库备份中。

注释

内存优化表在服务器重启期间重新编译。 为了加快数据库恢复速度,在服务器重启期间不会重新编译本机编译的存储过程,它们在首次执行时进行编译。 由于此延迟编译,本机编译的存储过程仅在首次执行后调用 sys.dm_os_loaded_modules(Transact-SQL) 时才显示。

维护 In-Memory OLTP DLL

以下查询显示服务器上当前加载到内存中的所有表和存储过程 DLL:

SELECT name, description FROM sys.dm_os_loaded_modules  
where description = 'XTP Native DLL'  

数据库管理员不需要维护由本机编译生成的文件。 SQL Server 会自动删除不再需要的生成的文件。 例如,删除表和存储过程或删除数据库时,将删除生成的文件。

注释

如果编译失败或中断,则不会删除某些生成的文件。 这些文件出于可支持性而被有意保留,在删除数据库时将被删除。

注释

在数据库启动期间,SQL Server 为数据库恢复所需的所有表编译 DLL。 如果在数据库重启之前删除了表,则检查点文件或事务日志中仍可能会有表的剩余部分,以便在数据库启动期间重新编译表的 DLL。 重启后,DLL 将卸载,文件将由正常清理过程删除。

表的原生编译

使用 CREATE TABLE 语句创建内存优化表会导致将表信息写入数据库元数据以及内存中创建的表和索引结构。 该表也将编译为 DLL。

请考虑以下示例脚本,该脚本创建数据库和内存优化表:

use master  
go  
create database db1  
go  
alter database db1 add filegroup db1_mod contains memory_optimized_data  
go  
-- adapt filename as needed  
alter database db1 add file (name='db1_mod', filename='c:\data\db1_mod') to filegroup db1_mod  
go  
use db1  
go  
create table dbo.t1  
   (c1 int not null primary key nonclustered,  
    c2 INT)  
with (memory_optimized=on)  
go  
-- retrieve the path of the DLL for table t1  
select name, description FROM sys.dm_os_loaded_modules  
where name like '%xtp_t_' + cast(db_id() as varchar(10)) + '_' + cast(object_id('dbo.t1') as varchar(10)) + '.dll'  
go  

创建表时,还会创建与该表相关的 DLL,并将该 DLL 加载到内存中。 在 CREATE TABLE 语句之后立即进行的 DMV 查询将检索表 DLL 的路径。

表 DLL 了解表的索引结构和行格式。 SQL Server 使用 DLL 遍历索引、检索行以及存储行的内容。

存储过程的本机编译

对使用 NATIVE_COMPILATION 来标记的存储过程执行本机编译。 这意味着过程中的 Transact-SQL 语句都编译为本机代码,以便高效执行性能关键型业务逻辑。

有关本机编译的存储过程的详细信息,请参阅 本机编译的存储过程

请考虑以下示例存储过程,该存储过程在上一个示例中插入表 t1 中的行:

create procedure dbo.native_sp  
with native_compilation, schemabinding, execute as owner  
as  
begin atomic  
with (transaction isolation level=snapshot, language=N'us_english')  
  
  declare @i int = 1000000  
  while @i > 0  
  begin  
    insert dbo.t1 values (@i, @i+1)  
    set @i -= 1  
  end  
  
end  
go  
exec dbo.native_sp  
go  
-- reset  
delete from dbo.t1  
go  

native_sp 的 DLL 可以直接与 t1 的 DLL 以及 In-Memory OLTP 存储引擎进行交互,以最快的速度插入数据行。

In-Memory OLTP 编译器利用查询优化器为存储过程中的每个查询创建有效的执行计划。 请注意,如果表中的数据发生更改,本机编译的存储过程不会自动重新编译。 有关使用 In-Memory OLTP 维护统计信息和存储过程的详细信息,请参阅 Memory-Optimized 表的统计信息

本地编译的安全注意事项

表和存储过程的本机编译使用 In-Memory OLTP 编译器。 此编译器生成写入磁盘并加载到内存的文件。 SQL Server 使用以下机制来限制对这些文件的访问。

本机编译器

编译器可执行文件以及本机编译所需的二进制文件和头文件作为文件夹 MSSQL\Binn\Xtp 下的 SQL Server 实例的一部分安装。 因此,如果默认实例安装在 C:\Program Files 下,则编译器文件安装在 C:\Program Files\MicrosoftSQL Server\MSSQL12中。MSSQLSERVER\MSSQL\Binn\Xtp。

为了限制对编译器的访问,SQL Server 使用访问控制列表(ACL)来限制对二进制文件的访问。 所有 SQL Server 二进制文件都通过 ACL 受到保护以防止修改或篡改。 本机编译器的 ACL 还会限制编译器的使用;只有 SQL Server 服务帐户和系统管理员对本机编译器文件具有读取和执行权限。

本机编译生成的文件

编译表或存储过程时生成的文件包括 DLL 和中间文件,包括扩展名为 .c、.obj、.xml和 .pdb 的文件。 生成的文件保存在默认数据文件夹的子文件夹中。 子文件夹称为 Xtp。 使用默认数据文件夹安装默认实例时,生成的文件将放置在 C:\Program Files\MicrosoftSQL Server\MSSQL12中。MSSQLSERVER\MSSQL\DATA\Xtp。

SQL Server 通过三种方式防止篡改生成的 DLL:

  • 将表或存储过程编译为 DLL 时,此 DLL 将立即加载到内存中并链接到 sqlserver.exe 进程。 链接到进程时,无法修改 DLL。

  • 重启数据库后,将基于数据库元数据重新编译所有表和存储过程(删除并重新创建)。 这将删除恶意代理对生成的文件所做的任何更改。

  • 生成的文件被视为用户数据的一部分,并且通过 ACL 与数据库文件具有相同的安全限制:只有 SQL Server 服务帐户和系统管理员才能访问这些文件。

无需用户交互即可管理这些文件。 SQL Server 将根据需要创建和删除文件。

另请参阅

Memory-Optimized 表
本机编译的存储过程