----------------------------我是分割線-------------------------------
本文翻譯自微軟白皮書《SQL Server In-Memory OLTP Internals Overview》:http://technet.microsoft.com/en-us/library/dn720242.aspx
譯者水平有限,如有翻譯不當之處,歡迎指正。
----------------------------我是分割線-------------------------------
表和存儲過程的本機編譯內存中OLTP將本機編譯的概念引入到了SQL Server 2014中。SQL Server可以在本機編譯訪問內存優化表的存儲過程,而且實際上,也本地編譯了內存優化表本身。本機編譯比起傳統的解釋型Transact-SQL可以提供更快的數據訪問和更高效的查詢執行。
什么是本機編譯?本地編譯是指將變編程結構轉換為本地代碼,包括可以由CPU直接執行的處理器指令,而不需要進一步的編譯或解釋的過程。
Transact-SQL語言由高層次的結構所組成,例如CREATE TABLE和SELECT... FROM。內存中OLTP編譯器分析這些結構,并將其編譯成本地代碼,以進行數據訪問和查詢執行的快速運行時間。SQL Server 2014中的內存中OLTP編譯器將表和存儲過程的定義做為輸入。它生成C語言代碼,并利用Visual C編譯器來生成本地代碼。
表和存儲過程編譯的結果為DLL文件,這些文件被加載到內存中并鏈接到SQL Server進程上。
SQL Server在創建內存優化表和本地編譯的存儲過程時,將它們編譯成本地DLL文件。另外,數據庫或服務器在重新啟動后,會重新編譯表和存儲過程的DLL文件。重建DLL文件所需的信息存儲在數據庫的元數據中;DLL文件本身并不是數據庫的一部分。因此DLL文件并不是數據庫備份的一部分。
DLL文件的維護內存優化表和本地編譯存儲過程的DLL文件,以及其他為了故障診斷和可支持性而保存的生成的文件,都存儲在文件系統中。
以下查詢顯示了當前服務器上加載到內存中的所有表和存儲過程的DLL文件:
SELECT name, description FROM sys.dm_os_loaded_modulesWHERE description = 'XTP Native DLL'
數據庫管理員不需要維護由本機編譯生成的文件。例如在表和存儲過程的刪除過程中,以及在刪除的數據庫中, SQL Server會自動刪除不再需要的生成文件,而且服務器或數據庫重新啟動時也會自動刪除。
表的本地編譯使用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語句之后的查詢檢索出表的DLL文件的路徑。
表t1的DLL文件能夠解析表的索引結構和行格式。 SQL Server使用這個DLL文件遍歷索引和檢索行,以及行中的內容。
存儲過程的本機編譯標有NATIVE_COMPILATION選項的存儲過程是本機編譯的。這意味著,為了性能要求較高的業務邏輯的執行效率,在存儲過程中的Transact-SQL語句都被編譯為本地代碼。
請參考以下的示例存儲過程,這個存儲過程將行插入到之前示例的表t1中:
CREATE PROCEDURE dbo.p1WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNERASBEGIN ATOMICWITH (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 ENDENDGOEXEC dbo.p1GO-- resetDELETE FROM dbo.t1GO
存儲過程p1的DLL文件可以直接與表t1的DLL文件以及內存中OLTP的存儲引擎進行交互,以便盡可能快的插入行。
內存中OLTP編譯器充分利用了查詢優化器為存儲過程中的每個查詢創建高效的執行計劃。需要注意的是,對于本機編譯的存儲過程,查詢執行計劃被編譯成DLL文件。由于SQL Server 2014不支持本機編譯的存儲過程的自動重新編譯,對表數據的修改可能需要刪除并重新創建一些存儲過程,將新的查詢計劃合并到存儲過程的DLL文件中。需要注意的是,在服務器重新啟動以及故障轉移到一個AlwaysOn副本后,本機編譯的存儲過程在第一次執行時進行重新編譯,這意味著查詢優化器將創建新的查詢計劃,新的查詢計劃隨后會被編譯到存儲過程的DLL文件中。
編譯和查詢處理圖15顯示了本機編譯的存儲過程的編譯過程:
圖15 存儲過程的本地編譯
1. 用戶向 SQL Server 發出一條CREATE PROCEDURE語句
2. 分析器和 algebrizer 為該存儲過程創建處理流程,并為存儲過程中的 Transact-SQL 查詢創建查詢樹
3. 優化器為存儲過程中的所有查詢創建優化的查詢執行計劃
4. 內存中 OLTP 編譯器通過嵌入的優化查詢計劃接管處理流程,并生成一個 DLL,其中包含執行存儲過程的機器代碼
5. 生成的 DLL 加載到內存中,并連接到SQL Server進程
本機編譯的存儲過程的調用轉換為對 DLL 中函數的調用,如圖16所示
圖16 本地編譯的存儲過程的執行
1. 用戶發出一條’EXEC myproc’語句
2. 分析器提取名稱和存儲過程參數
3. 內存中 OLTP 運行時查找存儲過程DLL文件的 入口點
4. DLL文件執行存儲過程邏輯,結果會返回到客戶端
參數嗅探
解釋型 Transact-SQL 存儲過程在首次執行(調用)時編譯成直接的物理執行計劃,而本機編譯的存儲過程在創建時編譯。當在調用時對解釋型存儲過程進行編譯,優化器使用為此調用提供的參數值生成執行計劃。這種編譯期間的參數用法稱為“參數嗅探”。
參數嗅探不適用于編譯本機編譯的存儲過程。此類存儲過程的所有參數都視為具有 UNKNOWN 值。
SQL Server的功能支持許多SQL Server功能都支持內存中OLTP和含內存優化表的數據庫,但不是所有SQL Server功能都支持。比如,AlwaysOn組件,日志傳送和數據庫的備份和恢復都完全支持內存中OLTP。事務復制部分支持,允許內存優化表作為一個訂閱使用,但不能作為發布項目。但是,不支持數據庫鏡像。可以使用SQL Server Management Studio來管理內存優化表,也支持SSIS。
有關支持和不支持功能的完整列表,請參閱SQL Server內存中OLTP的文檔。
管理經驗內存中OLTP已完全集成到SQL Server的管理經驗中。正如上面提到的,SQL Server Management Studio中能夠管理內存優化表,文件組和本地編譯的存儲過程。還可以使用SQL Server管理對象(SMO)和PowerShell來管理您的內存優化對象。
元數據一些已有的元數據對象已經得到增強,可提供關于內存優化表和存儲過程的信息,新的對象也已經增加。
有一個函數得到了增強:
以下的系統視圖得到增強:
此外,還有一些專門提供內存優化表信息的幾個新的元數據對象。
增加了一個新的目錄視圖來支持哈希索引:sys.hash_indexes。這個視圖是基于sys.indexes,因此具有和sys.indexes相同的列,并有一個額外添加的列。這個bucket_count列顯示了為索引所指定的哈希桶的數量,而且如果沒有刪除和重建索引的話,這個值不會被改變。
動態管理對象以下SQL Server動態管理視圖是為內存中OLTP所新增的。 (xtp標識符代表“極限事務處理(eXtreme transaction processing)”。)sys.dm_db_xtp_*開頭的那些動態管理視圖提供了關于啟用內存中OLTP的各個數據庫的信息, sys.dm_xtp_*開頭的那些動態管理視圖提供了實例級別的信息。您可以在文檔中讀到關于這些對象的詳細信息。這些動態管理視圖中的一些在本文較早的相關章節已經提到過。
關于支持內存優化表的動態管理視圖的詳細信息,請參閱內存優化表的動態管理視圖。
內存中OLTP引擎提供了xEvents來幫助監控和故障排除。您可以運行以下查詢來查看當前可用的xEvents:
SELECT p.name, o.name, o.descriptionFROM sys.dm_xe_objects o JOIN sys.dm_xe_packages pON o.package_guid=p.guidWHERE p.name = 'XtpEngine';GO性能計數器
內存中OLTP引擎提供了性能計數器來幫助監控和故障排除。您可以運行以下查詢來查看當前可用的性能計數器:
SELECT OBJECT_NAME,counter_namefrom sys.dm_os_performance_countersWHERE OBJECT_NAME LIKE'XTP%';GO
還提供了名為XTP使用內存的數據庫計數器對象,用于跟蹤在數據庫級別的內存優化表的內存使用情況。
內存使用情況報表要獲得內存優化表和索引當前使用內存的實時報表,您可以運行SQL Server Management Studio中提供的報表。在對象資源管理器中,右鍵單擊包含內存優化表的數據庫的名稱,選擇報表|標準報表|內存優化對象的內存使用情況。您會看到類似圖17的報表。
圖17內存優化對象的內存使用情況報表
這個報表顯示表的行和索引所使用的空間,以及少量由系統使用的空間。請記住,一旦創建了哈希索引,這些索引就會擁有分配給已聲明的哈希桶數量的內存,因此這個報表將顯示在插入任何行之前,這些索引的內存使用情況。對于非聚集索引,在添加行之前不會分配內存,并且內存需求將依賴于索引鍵的大小和行的數量。
內存需求當運行內存中OLTP時,SQL Server需要配置足夠的內存來保存所有的內存優化表。未能分配足夠的內存會導致在需要額外內存的操作運行時事務失敗。通常這會在INSERT或UPDATE操作時發生,但在一個內存優化的非聚集索引上的刪除操作也有可能發生。正如上一節所介紹的,刪除可能導致產生頁合并,而且由于索引頁永遠不會被更新,合并操作將會分配新頁。內存中OLTP的內存管理器與SQL Server的內存管理器完全集成,并在可能的情況下,通過更積極地清理舊行版本來對內存壓力進行反應。
在預測內存優化表所需的內存數量時,一個經驗法是,應該擁有數據占用量兩倍的內存。除此之外,總內存需求還取決于工作負荷;如果由于OLTP操作有大量的數據修改,則需要更多的內存供給行版本使用。如果大量讀取現有的數據,則可能需要更少的內存。
對于規劃索引所需的空間,哈希索引則非常簡單。每個桶需要8個字節,所以您可以計算桶的數量乘以8字節數。內存優化非聚集索引的大小取決于索引鍵的大小和表中行的數量??梢约僭O每個索引行是8個字節加上索引鍵的大?。僭O為k字節),因此,適合于一個頁面的最大行數將是8176/(K +8)。預計的行數除以這個結果將得到一個初步的估計。請記住,并不是所有的索引頁都是8K,也不是所有的頁都是全滿的。由于頁需要拆分和合并,創建出新的頁,需要為這些頁留出空間,直到垃圾收集進程將它們刪除。
用資源調控器管理內存SQL Server的資源調控器是一種讓您可以主動管理內存的工具。與CTP2版本開始,數據庫可以綁定到一個資源池上,您可以分配一定量的內存到這個池中。這個數據庫中的內存優化表使用的內存不能超過這個量。有一個可分配內存的80%的固定限制,以確保系統在內存壓力下仍然穩定。事實上,內存優化表及其索引占用的任何內存都是由資源調控器管理,除此之外,并沒有其他類型的內存是由資源調控器管理。如果數據庫沒有顯式映射到一個資源池,它會隱式地映射到默認池。
更多有關SQL Server資源調控器的詳細信息,請參閱SQL Server 2008引入資源調控器時編寫的擴展白皮書:http://view.officeapps.live.com/op/view.aspx?src=http%3A%2F%2Fdownload.microsoft.com%2Fdownload%2FD%2FB%2FD%2FDBDE7972-1EB9-470A-BA18-58849DB3EB3B%2FResourceGov.docx
SQL Server2012中資源調控器的更改,可以在這里讀到:http://msdn.microsoft.com/en-us/library/jj573256.aspx
為內存中OLTP數據庫創建一個內存池的第一步是指定MAX_MEMORY_PERCENT值。這個值指定了可以被分配給與這個池關聯數據庫中內存優化表的SQL Server內存的百分比。
例如:
CREATE RESOURCE POOL HkPool WITH (MAX_MEMORY_PERCENT=50);ALTER RESOURCE GOVERNOR RECONFIGURE;
創建了資源池之后,需要使用存儲過程sp_
新聞熱點
疑難解答