除了記憶體優化數據表(用於有效率的數據存取)和原生編譯預存程式(用於有效率的查詢處理和商業規則執行),In-Memory OLTP 引進了第三種物件:記憶體優化數據表類型。 使用記憶體優化數據表類型建立的數據表變數是記憶體優化數據表變數。
相較於磁碟數據表變數,記憶體優化數據表變數可提供下列優點:
變數只會儲存在記憶體中。 數據存取更有效率,因為記憶體優化表類型使用與記憶體優化表相同的記憶體優化算法和數據結構,尤其是在原生編譯的預存程序中使用變數時。
在使用記憶體優化的表格變數時,不會使用tempdb。 數據表變數不會儲存在tempdb中,也不會使用tempdb中的任何資源。
記憶體優化數據表變數的一般使用案例如下:
儲存中繼結果,並根據原生編譯預存程式中的多個查詢建立單一結果集。
將數據表值參數傳遞至原生編譯的預存程式和解譯的預存程式。
取代基於磁碟的表變數,以及在某些情況下存儲過程中本地的 #temp表。 如果系統中有許多tempdb爭用,這會特別有用。
表格變數可用來模擬原生編譯預存程式中的游標,這可協助您解決原生編譯預存程式中的表面區域限制。
如同記憶體優化數據表,SQL Server 會為每個記憶體優化數據表類型產生 DLL。 (在建立記憶體最佳化資料表類型時會叫用編譯,而不是在用來建立記憶體最佳化資料表變數時叫用。)此 DLL 包含用來存取索引和從資料表變數擷取資料的函式。 根據數據表類型宣告記憶體優化數據表變數時,會在使用者會話中建立對應至數據表類型的數據表和索引結構的實例。 然後,可以使用與磁碟數據表變數相同的方式來使用數據表變數。 您可以在資料表變數中插入、更新和刪除資料列,並在 Transact-SQL 查詢中使用變數。 您也可以將變數傳遞至原生編譯和解譯的預存程式,做為數據表值參數 (TVP)。
下列範例顯示 AdventureWorks 型 In-Memory OLTP 範例中的記憶體優化數據表類型(SQL Server 2014 In-Memory OLTP 範例)。
CREATE TYPE Sales.SalesOrderDetailType_inmem
AS TABLE
(
OrderQty smallint NOT NULL,
ProductID int NOT NULL,
SpecialOfferID int NOT NULL
INDEX IX_SpecialOfferID NONCLUSTERED,
LocalID int NOT NULL,
INDEX IX_ProductID HASH (ProductID)
WITH ( BUCKET_COUNT = 8 )
)
WITH ( MEMORY_OPTIMIZED = ON );
此範例顯示記憶體優化數據表類型的語法類似於以磁碟為基礎的數據表類型,但有下列例外狀況:
MEMORY_OPTIMIZED=ON表示數據表類型為記憶體優化。類型必須至少有一個索引。 如同記憶體優化數據表,您可以使用哈希和非叢集索引。
對於哈希索引,貯體計數應該大約是預期唯一索引鍵數目的一到兩倍。 如需詳細資訊,請參閱 確定哈希索引的正確桶數。
記憶體優化數據表的數據類型和條件約束限制也適用於記憶體優化數據表類型。 例如,在 SQL Server 2014 中支援預設條件約束,但不支援檢查條件約束。
和記憶體優化數據表、記憶體優化數據表變數一樣
不支援平行計劃。
必須放入記憶體中,且不使用磁碟資源。
以磁碟為基礎的數據表變數存在於tempdb中。 記憶體優化數據表變數存在於用戶資料庫中(但不會取用記憶體,也不會復原)。
您無法使用內嵌語法建立記憶體優化數據表變數。 不同於磁碟數據表變數,您必須先建立類型。
Table-Valued 參數
下列範例文本顯示資料表變數宣告為記憶體優化數據表類型 Sales.SalesOrderDetailType_inmem、將三個數據列插入變數,並將變數當做TVP傳遞至 Sales.usp_InsertSalesOrder_inmem。
DECLARE @od Sales.SalesOrderDetailType_inmem,
@SalesOrderID uniqueidentifier,
@DueDate datetime2 = SYSDATETIME()
INSERT @od (LocalID, ProductID, OrderQty, SpecialOfferID) VALUES
(1, 888, 2, 1),
(2, 450, 13, 1),
(3, 841, 1, 1)
EXEC Sales.usp_InsertSalesOrder_inmem
@SalesOrderID = @SalesOrderID,
@DueDate = @DueDate,
@OnlineOrderFlag = 1,
@SalesOrderDetails = @od
記憶體已優化的資料表類型可以用作預存程序的資料表值參數(TVP)的類型,用戶端可以像參考磁碟型資料表類型和 TVP 一樣來參考它們。 因此,使用記憶體優化的 TVP 調用預存程序時,原生編譯的預存程序與使用磁碟型 TVP 的解譯預存程序調用方式完全相同。
#temp 表替換
下列範例顯示記憶體最佳化資料表類型和資料表變數,以取代預存程序內的區域 #temp 資料表。
-- Using SQL procedure and temp table
CREATE TABLE #tempTable (c INT NOT NULL PRIMARY KEY NONCLUSTERED)
CREATE PROCEDURE sqlProc
AS
BEGIN
TRUNCATE TABLE #tempTable
INSERT #tempTable VALUES (1)
INSERT #tempTable VALUES (2)
INSERT #tempTable VALUES (3)
SELECT * FROM #tempTable
END
GO
-- Using natively compiled stored procedure and table variable
CREATE TYPE TT AS TABLE (c INT NOT NULL PRIMARY KEY NONCLUSTERED)
GO
CREATE PROCEDURE NCSPProc
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS
BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english')
DECLARE @tableVariable TT
INSERT @tableVariable VALUES (1)
INSERT @tableVariable VALUES (2)
INSERT @tableVariable VALUES (3)
SELECT c FROM @tableVariable
END
GO
建立單一結果集
下列範例示範如何儲存中繼結果,並根據原生編譯預存程式中的多個查詢建立單一結果集。 此範例正在計算聯集 SELECT c1 FROM dbo.t1 UNION SELECT c1 FROM dbo.t2。
CREATE DATABASE hk
GO
ALTER DATABASE hk ADD FILEGROUP hk_mod CONTAINS MEMORY_OPTIMIZED_DATA
ALTER DATABASE hk ADD FILE( NAME = 'hk_mod' , FILENAME = 'c:\data\hk_mod') TO FILEGROUP hk_mod;
USE hk
GO
CREATE TYPE tab1 AS TABLE (c1 INT NOT NULL, INDEX idx NONCLUSTERED(c1)) WITH (MEMORY_OPTIMIZED = ON)
CREATE TABLE dbo.t1 (c1 INT NOT NULL, INDEX idx NONCLUSTERED(c1)) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY)
CREATE TABLE dbo.t2 (c1 INT NOT NULL, INDEX idx NONCLUSTERED(c1)) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY)
INSERT INTO dbo.t1 VALUES (1), (2)
INSERT INTO dbo.t2 VALUES (3), (4)
GO
CREATE PROCEDURE dbo.p1
WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER
AS
BEGIN ATOMIC WITH ( TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english' )
DECLARE @t dbo.tab1
INSERT @t (c1)
SELECT c1 FROM dbo.t1;
INSERT @t (c1)
SELECT c1 FROM dbo.t2;
SELECT c1 FROM @t;
END
GO
EXEC dbo.p1
GO
數據表變數的記憶體耗用量
數據表變數的記憶體耗用量類似於記憶體優化數據表,但非叢集索引除外。 如果您使用非叢集索引將大量數據列插入記憶體優化數據表變數,而且索引鍵很大,則這些數據表變數會使用不成比例的記憶體數量。 大型表格變數上的非叢集索引需要比在常規表格中插入相同數量列時所需的非叢集索引使用更多的記憶體(在索引頁中需要更多記憶體)。
數據表變數的記憶體來自資料庫的 Resource Governor 資源集區。
不同於記憶體優化數據表,當數據表變數超出範圍時,會釋出數據表變數所耗用的記憶體(包括已刪除的數據列)。
記憶體會視為資料庫單一 PGPOOL 記憶體取用者的一部分。