1. 程式人生 > >將一個基於磁盤的表遷移到SQL Server中的一個內存優化的表

將一個基於磁盤的表遷移到SQL Server中的一個內存優化的表

varchar 並發 ken 希望 重要 資源管理器 limited com arc

本文是微軟的譯文,對應的原文是:https://www.red-gate.com/simple-talk/sql/database-administration/migrating-disk-based-table-memory-optimized-table-sql-server/

以前稱為Hekaton的特性,現在是內存中的OLTP,可以提供非常有用的性能提升,您可以仔細地選擇表來進行內存優化。如何將現有表轉換為內存優化的表呢?這個過程不是很簡單,但是內存中的OLTP表所帶來的好處是值得您付出努力的。Alex Grinberg帶著你的基本知識。

內存中的OLTP,也稱為Hekaton,可以顯著提高OLTP(聯機事務處理)數據庫應用程序的性能。它提高了吞吐量,減少了事務處理的延遲,並且可以幫助改善數據暫態的性能,比如臨時表和ETL期間(提取轉移和加載)。內存中的OLTP是一種內存優化的數據庫引擎,它集成到SQL Server引擎中,並針對事務處理進行了優化。

為了使用內存中的OLTP,您將一個重訪問的表定義為內存優化。內存優化的表是完全事務性的、持久的,並且可以使用與基於磁盤的表相同的方式訪問。一個查詢可以同時引用Hekaton內存優化表和基於磁盤的表。事務可以在Hekaton表和基於磁盤的表中更新數據。只引用內存優化表的存儲過程可以被本機編譯為機器代碼,以便進行進一步的性能改進。內存中的OLTP引擎是為一個非常高的會話而設計的

註意:在SQL Server 2014中引入了內存優化的OLTP表。不幸的是,它有許多限制,因此使用起來很不實際。在SQL Server 2016中,內存優化的表得到了極大的改進,並且大大減少了約束。在SQL Server 2016版本中,只有幾個限制仍然存在。本節提供的所有示例和技術只適用於SQL Server 2016版本。

在開始使用內存優化的表之前,必須使用一個memory最優化數據filegroup來創建一個數據庫。這個filegroup用於存儲SQL Server需要的數據和delta文件對來恢復內存優化的表。盡管創建它們的語法與創建常規filestream filegroup的語法幾乎相同,但它也必須指定包含memory優化數據選項。

創建

CREATE DATABASE [TestDB]

ON PRIMARY

( NAME = N‘TestDB_data‘, FILENAME = N‘C:\SQL2016\TestDB_data.mdf‘),

FILEGROUP [TestDBSampleDB_mod_fg] CONTAINS MEMORY_OPTIMIZED_DATA DEFAULT

( NAME = N‘TestDB_mod_dir‘, FILENAME = N‘C:\SQL2016\TestDB_mod_dir‘ , MAXSIZE = UNLIMITED)

LOG ON

( NAME = N‘TestDBSampleDB_log‘, FILENAME = N‘C:\SQL2016\TestDB_log.ldf‘ )

如果希望為現有數據庫啟用memory最優化數據選項,則需要使用memory優化數據選項創建一個filegroup,然後將文件添加到filegoup中。

ALTER DATABASE [TestDB] ADD FILEGROUP [TestDBSampleDB_mod_fg] CONTAINS MEMORY_OPTIMIZED_DATA; ALTER DATABASE [TestDB] ADD FILE (NAME=‘TestDB_mod_dir‘, FILENAME=‘C:\SQL2016\TestDB_mod_dir‘) TO FILEGROUP [TestDBSampleDB_mod_fg]; 執行下面的SQL代碼,以驗證是否啟用了一個數據庫內存優化數據選項。 USE TestDB SELECT g.name, g.type_desc, f.physical_name FROM sys.filegroups g JOIN sys.database_files f ON g.data_space_id = f.data_space_id WHERE g.type = ‘FX‘ AND f.type = 2 作為檢查memory優化數據的另一種選擇:打開數據庫屬性,選擇Filegroups,在memory優化數據選項中顯示filegroup名稱。 技術分享 下面是基於磁盤的表和內存優化表之間的差異列表: MEMORY_OPTIMIZED property –當訪問內存優化的表時,不需要從磁盤讀取這些頁面。所有的數據都存儲在內存中。 DURABILITY property –內存優化的表可以是持久的(schemaanddata),也可以是非持久的(模式)。默認情況下,這些表是持久的(schemaanddata),這些持久表也滿足了所有其他事務需求;它們是原子的、孤立的、一致的。一組檢查點文件(數據和delta文件對),這些文件只用於恢復目的,是使用駐留在內存優化的文件組中的操作系統文件創建的,這些文件組跟蹤對持久表中的數據的更改。這些檢查點文件只是應用程序。非持久的,沒有記錄的,只使用一個選項模式。正如該選項所指出的,表模式將是持久的,即使數據不是。在事務處理過程中,這些表不需要任何IO操作,也不需要對這些表的檢查點文件進行任何操作。只有在SQL
Server運行時,數據才可以在內存中使用。 Indexes –沒有在內存優化的表上實現集群索引。索引不是作為傳統的b樹存儲的。內存優化的表支持散列索引,存儲為哈希表,其中有鏈表,將散列的所有行連接到相同的值和“範圍”索引,這些索引是使用特殊的bw樹存儲的。使用bw-tree的範圍索引可以用來快速查找範圍謂詞中的符合條件的行,就像傳統的b-樹一樣,但是它是用樂觀的並發控制設計的,沒有鎖定或鎖定。 將基於磁盤的磁盤遷移到內存優化的OLTP表 表是列和行的集合。為了將基於磁盤的表遷移到內存優化的表,有必要了解內存優化的表列數據類型的限制。 不支持以下數據類型:datetimeoffset, geography, geometry, hierarchyid, rowversion, xml, sql_variant, all User-Defined Types and all legacy LOB data types (including text, ntext, and image) 支持數據類型包括: bit, tinyint, smallint, int, bigint. Numeric and decimal
  • money and smallmoney
  • float and real
  • date/time types: datetime, smalldatetime, datetime2, date and time
  • char(n), varchar(n), nchar(n), nvarchar(n), sysname, varchar(MAX) and nvarchar(MAX)
  • binary(n), varbinary(n) and varbinary(MAX)
  • Uniqueidentifier

創建內存優化的表的語法與創建基於磁盤的表的語法幾乎完全相同,有一些限制,以及一些必要的擴展。其中的一些區別是:

要設置 MEMORY_OPTIMIZED = ON

The DURABILITY property is set to SCHEMA_AND_DATA or SCHEMA_ONLY (SCHEMA_AND_DATA is default)

The memory-optimized table must have a PRIMARY KEY index. If HASH index is selected for the primary key, then BUCKET_COUNT must be specified.

在內存優化表中只允許包括主鍵在內的8個索引

IDENTITY properties have to be set as seed = 1 and increment = 1 only.

在內存優化的表中不允許計算列(Computed Columns)

不加選擇地創建內存優化的表是一個壞主意。同時,對於OS和其他SQL服務器進程也需要內存,將盡可能多的表遷移到內存優化的表中並不是一個好主意。因為內存優化的表是用開放式並發控制設計的,沒有鎖定或被鎖,選擇轉換的最佳表應該是具有“鎖定和鎖定配置文件”(被檢測為會話“攔截器”的表)的表,其中包括最可寫的表(插入、更新和刪除)和最可讀的表,然而,這個列表對於遷移來說還不是很完整。但是,不應該遷移的表是靜態元數據表;違反了內存優化表的限制的表;表的行數更少。

在SQL Server 2016中,可以使用SQL Server
PowerShell生成一個遷移清單。在對象資源管理器中,右鍵單擊一個數據庫,然後單擊Start PowerShell;驗證以下提示出現,執行以下代碼:PS SQLSERVER:\SQL\{Instance Name}\DEFAULT\Databases\{DB Name}>

輸入以下命令(用您的目標文件夾路徑替換C:Temp。如果您喜歡使用更通用的方法$Env:Temp或$Env:報告輸出的路徑,然後驗證這些命令的PowerShell路徑。只需運行$Env:Temp或$Env:PowerShell命令窗口中的路徑,您的本地路徑將被返回)。清單PowerShell命令示例:

Save-SqlMigrationReportFolderPathC:\Temp”

註意:如果您需要在單個表上運行遷移報告,那麽就展開數據庫節點,展開表節點,右鍵單擊表,然後從彈出菜單中選擇Start PowerShell。

文件夾路徑將被創建,以防它不存在。遷移檢查表報告將為數據庫中的所有表和存儲過程生成,並且報告將出現在FolderPath指定的位置。因此,報告的文件夾路徑將被指定為PowerShell腳本中的FolderPath,以及檢查清單執行的數據庫名稱。在這個例子中,它是C:\Temp\Northwind.

檢查表報告可以指出,已經超過了內存優化表的一個或多個數據類型限制。但是,這並不意味著不能將表遷移到內存優化的表中。報告指出每一列是否滿足了成功的標準,如果沒有,則提示如果表對遷移很重要,那麽如何糾正問題。例如,一個數據庫有一個表testdisk。為了演示的目的,我們將在稍後的報告中看到這個表,其中包含了大量的遷移違規行為。

CREATE TABLE dbo.TEST_Disk( ID int IDENTITY(10000, 1), ProductID int NOT NULL, OrderQty int NOT NULL, SumOrder as ProductID + OrderQty, XMLData XML NULL, Description varchar(1000) SPARSE, StartDate datetime CONSTRAINT DF_TEST_DiskStart DEFAULT getdate() NOT NULL, ModifiedDate datetime CONSTRAINT DF_TEST_DiskEnd DEFAULT getdate() NOT NULL, CONSTRAINT PK_TEST_Disk_ID PRIMARY KEY CLUSTERED ( ID ) ) 遷移清單完成後,我們有以下報告:
  • XMLData column have XML data type
  • SumOrder is Computed Column
  • Description column is SPARSE
  • ID have IDENTITY seed value 10000

根據這份報告,所有的違規行為都必須得到糾正,或者不能遷移表格。讓我們修正所有這些違規行為:

XMLData列將被轉換為nv(MAX)數據類型;這就是XML的本質。但是,當應用程序或數據庫沒有實現UNICODE時,可以考慮VARCHAR(MAX)數據類型。

SumOrder是計算的列,其中的值通過公式ProductID列進行計算,並使用OrderQty列(公式ProductID+OrderQty僅為演示目的而創建)。ProductID和OrderQty列都有int數據類型。因此,SumOrder列從ProductID和OrderQty列中繼承了int數據類型(如何糾正計算的列問題,將在“修復計算列問題”小節中解釋)。

Description列,為了糾正這個問題,只需刪除稀疏選項

ID column IDENTITY:將對應的seed value設置成1

在實現了所有的更正之後,testmemory內存優化表的DDL腳本將會是:

CREATE TABLE dbo.TEST_Memory( ID int IDENTITY(1, 1), ProductID int NOT NULL, OrderQty int NOT NULL, SumOrder int NULL, XMLData nvarchar(MAX) NULL, Description varchar(1000) NULL, StartDate datetime CONSTRAINT DF_TEST_MemoryStart DEFAULT getdate() NOT NULL, ModifiedDate datetime CONSTRAINT DF_TEST_MemoryEnd DEFAULT getdate() NOT NULL, CONSTRAINT PK_TEST_Memory_ID PRIMARY KEY NONCLUSTERED HASH ( ID )WITH (BUCKET_COUNT = 1572864) ) WITH ( MEMORY_OPTIMIZED = ON , DURABILITY = SCHEMA_AND_DATA ) 現在,我們需要將IDENTITY seed設置為10,000,但是,內存優化的表不支持DBCC命令來重置標識,設置IDENTITY_INSERT TEST_Memory ON將為我們完成 -- 1. Insert dummy row SET IDENTITY_INSERT TEST_Memory ON INSERT TEST_Memory (ID,ProductID, OrderQty, SumOrder) SELECT 10000, 1,1,1 SET IDENTITY_INSERT TEST_Memory OFF -- 2. Remove the record DELETE TEST_Memory WHERE ID = 10000 -- 3. Verify Current Identity SELECT TABLE_NAME, IDENT_SEED(TABLE_NAME) AS Seed, IDENT_CURRENT(TABLE_NAME) AS Current_Identity FROM INFORMATION_SCHEMA.TABLES WHERE OBJECTPROPERTY(OBJECT_ID(TABLE_NAME), ‘TableHasIdentity‘) = 1 AND TABLE_NAME = ‘TEST_Memory‘ 當所有這三個步驟都被應用時,您將把IDENTITY設置為10,000的所需值。 現在我們將加載一些測試數據。為了準備好大量的行,我們將通過下面的SQL腳本創建一個testdataload表,以便將100萬行裝載到表中。本文將介紹所有的SQL語法 ;With ZeroToNine (Digit) As (Select 0 As Digit Union All Select Digit + 1 From ZeroToNine Where Digit < 9), OneMillionRows (Number) As ( Select Number = SixthDigit.Digit * 100000 + FifthDigit.Digit * 10000 + FourthDigit.Digit * 1000 + ThirdDigit.Digit * 100 + SecondDigit.Digit * 10 + FirstDigit.Digit * 1 From ZeroToNine As FirstDigit Cross Join ZeroToNine As SecondDigit Cross Join ZeroToNine As ThirdDigit Cross Join ZeroToNine As FourthDigit Cross Join ZeroToNine As FifthDigit Cross Join ZeroToNine As SixthDigit ) Select Number+1 ID,ABS(CHECKSUM(NEWID())) % 50 ProductID, ABS(CHECKSUM(NEWID())) % 55 OrderQty , (SELECT Number+1 as ProductID,ABS(CHECKSUM(NEWID())) % 50 as OrderQty FROM master.dbo.spt_values as data WHERE type = ‘p‘ and data.number = v.number % 2047 FOR XML AUTO, ELEMENTS, TYPE ) XMLData INTO TEST_DataLoad From OneMillionRows v 當testdataload準備就緒時,讓我們為基於磁盤的和內存優化的表運行一個測試負載。服務器上有32個CPU;512
GB的內存;核聚變(固態)驅動器。但是,內存優化的表執行的速度是磁盤表的兩倍多。
---- Load disk-based table SET STATISTICS TIME ON; INSERT [dbo].[TEST_Disk] ( ProductID, OrderQty ) select ProductID, OrderQty from TEST_DataLoad SET STATISTICS TIME OFF; SQL Server Execution Times: CPU time = 5968 ms, elapsed time = 6322 ms. ---- Load the memory-optimized table SET STATISTICS TIME ON; INSERT [dbo].[TEST_Memory](ProductID, OrderQty, SumOrder) select ProductID, OrderQty,ProductID + OrderQty from TEST_DataLoad SET STATISTICS TIME OFF; SQL Server Execution Times: CPU time = 2500 ms, elapsed time = 2561 ms.

將一個基於磁盤的表遷移到SQL Server中的一個內存優化的表