SQL Server中的内存优化表变量

本文介绍了SQL Server内存优化表变量的使用,对比了它们与基于磁盘的表变量的性能。内存优化表变量因低延迟和高吞吐量而提高性能,不受TempDB性能问题影响。文章还涵盖了内存优化表类型的创建和特性,以及性能基准测试,证明了内存优化表变量在处理大量数据时的优越性能。
摘要由CSDN通过智能技术生成

This article will cover the usage details and performance advantages of the memory-optimized table variables.

本文将介绍内存优化表变量的用法细节和性能优势。

A table variable is a sort of variable that is used to store data temporarily. Disk-based table variables are created in the TempDB database by SQL Server and their life cycle begins and ends on this database. In this context, database performance issues in TempDB directly influence the performance of the disk-based table variables.

表变量是一种用于临时存储数据的变量。 SQL Server在TempDB数据库中创建基于磁盘的表变量,它们的生命周期在该数据库上开始和结束。 在这种情况下,TempDB中的数据库性能问题直接影响基于磁盘的表变量的性能。

With the SQL Server 2014 version, the memory-optimized tables were introduced and they are impacting performance positively due to low-latency and high throughput benefits. There are two durability options available for the memory-optimized tables.

在SQL Server 2014版本中,引入了内存优化表,由于低延迟和高吞吐量的优势,它们对性能产生了积极影响。 对于内存优化的表,有两个可用的耐用性选项。

SCHEMA_AND_DATA option enables us to preserve schema and data at the same time so we don’t carry any losing data risk.

SCHEMA_AND_DATA选项使我们能够同时保留架构和数据,因此我们不会承担任何丢失数据的风险。

SCHEMA_ONLY option preserves only the schema of the table. For this reason, we lose the data when the server is restarted. Particularly, non-durable memory-optimized tables produce zero disks I/O because they solely use the memory resources to store the data. On the other hand, data does not preserve on disk, it means that if the SQL Server engine is restarted, we will lose the data but table schema will be re-created. The memory-optimized table variable offers advanced performance with the minimum latency by using the memory-optimized infrastructure. Also, if we decide to use them we don’t require any application code changes.

SCHEMA_ONLY选项仅保留表的架构。 因此,重新启动服务器时我们会丢失数据。 特别是,非持久的内存优化表产生零磁盘I / O,因为它们仅使用内存资源来存储数据。 另一方面,数据不会保留在磁盘上,这意味着如果重新启动SQL Server引擎,我们将丢失数据,但将重新创建表架构。 通过使用内存优化的基础架构,内存优化的表变量以最小的延迟提供了高级性能。 另外,如果我们决定使用它们,则不需要任何应用程序代码更改。

什么是内存优化表类型? (What is the memory-optimized table type?)

The memory-optimized table type is used to specify a predefined table definition. The following query will create a memory-optimized table type.

内存优化的表类型用于指定预定义的表定义。 以下查询将创建内存优化的表类型。

CREATE TYPE CustomerType AS TABLE
(CustomerID         INT NOT NULL, 
 CustomerName       NVARCHAR(100) NOT NULL, 
 CustomerCreateDate DATETIME NOT NULL, 
 INDEX IDX HASH(CustomerID)
 WITH(BUCKET_COUNT = 100)
) WITH
(MEMORY_OPTIMIZED = ON
)

In this syntax, some keywords may draw our attention to their differences;

使用这种语法,某些关键字可能会引起我们对它们的区别的注意;

MEMORY_OPTIMIZED = ON syntax identifies that this table type will be on the memory-optimized structure. Memory-optimized tables need at least one index to connect rows. This index can be a hash index or a nonclustered index. Individually for this table type, we chose the hash index type so we must set the bucket number. This number specifies the bucket number of the hash index.

MEMORY_OPTIMIZED = ON语法标识此表类型将在内存优化的结构上。 内存优化表至少需要一个索引才能连接行。 该索引可以是哈希索引或非聚集索引。 单独为此表类型选择哈希索引类型,因此必须设置存储桶编号。 该数字指定哈希索引的存储桶编号。

Tip: For memory-optimized tables we can use two types of indexes. Hash Index offers advanced performance to seek equality values. The nonclustered index will be a good option to seek the range value conditions.

提示:对于内存优化表,我们可以使用两种类型的索引 哈希索引提供了先进的性能以寻求平等价值。 非聚集索引将是寻求范围值条件的一个很好的选择。

When we create any memory-optimized table type, it will be shown under the Types folder in SQL Server Management Studio.

当我们创建任何内存优化表类型时,它将显示在SQL Server Management Studio的Types文件夹下。

Find table types in SSMS

When we right-click on the CustomerType and select Properties menu, we can find out the details of the memory-optimized table type. On this screen, the Memory Optimized option shows the type of table type.

当我们右键单击CustomerType并选择Properties菜单时,我们可以找到内存优化表类型的详细信息。 在此屏幕上,“ 内存优化”选项显示表类型的类型。

User-defined table type screen in the SSMS

内存优化表变量 (Memory-optimized table variable)

Memory-optimized table variables do not consume the TempDB resources so they are not affected by any contention and latency issues of the TempDB database. At the same time, they give an outstanding performance relative to disk-based table variables to access the data. We will apply the following steps to create a memory-optimized table variable.

内存优化的表变量不会消耗TempDB资源,因此不会受到TempDB数据库的任何争用和延迟问题的影响。 同时,相对于基于磁盘的表变量访问数据,它们具有出色的性能。 我们将采用以下步骤来创建内存优化的表变量。

  • Type a DECLARE statement to initialize a variable

    输入DECLARE语句以初始化变量
  • Assign a name to the variable and this name must start with @ sign

    为变量分配一个名称,该名称必须以@符号开头
  • Assign it to a memory-optimized table type after the AS keyword

    在AS关键字之后将其分配给内存优化的表类型
  • CRUD operations can be performed

    可以执行CRUD操作
DECLARE @TestTableVar AS CustomerType 
INSERT INTO @TestTableVar VALUES(1,'Henry Lawrence', '20200305') 
SELECT * FROM @TestTableVar

Creating Memory-optimized table variable

Now we will prove zero I/O concept of this table variable types. After enabling the STATISTICS IO option, the query editor displays the statistical values of the disk activity generated by the query. We will enable this option for the previous query and will execute it.

现在,我们将证明此表变量类型的零I / O概念。 启用S​​TATISTICS IO选项后,查询编辑器将显示查询生成的磁盘活动的统计值。 我们将为上一个查询启用此选项并执行它。

SET STATISTICS IO ON
GO
DECLARE @TestTableVar AS CustomerType 
INSERT INTO @TestTableVar VALUES(1,'Henry Lawrence', '20200305') 
SELECT * FROM @TestTableVar

Test disk IO of the memory-optimized table variable

The result is not surprising, we have not seen any I/O activity because it uses the memory-optimized algorithm.

结果不足为奇,因为它使用内存优化算法,所以我们没有看到任何I / O活动。

The memory-optimized table variables allow us to create the following constraints and we can define these constraints with the declaration of the table type.

内存优化的表变量使我们可以创建以下约束,并且可以使用表类型的声明来定义这些约束。

  • Unique

    独特
  • Null

    空值
  • Check

    检查一下
CREATE TYPE MemoryTypeCons AS TABLE
(ID INT PRIMARY KEY NONCLUSTERED,
Col1 VARCHAR(40) UNIQUE,
Col2 VARCHAR(40) NOT NULL,
Col3 int CHECK (Col3>=20)
) WITH
(MEMORY_OPTIMIZED = ON
)
GO
DECLARE @ConsTable AS MemoryTypeCons
INSERT INTO @ConsTable
VALUES(1,'Value1',12 , 20)
SELECT * FROM @ConsTable

How to use constraints with memory-optimized table variable

Memory-optimized table variables do not allow to create a clustered index, for this reason, we have to define primary key constraint as a nonclustered.

内存优化的表变量不允许创建聚簇索引,因此,我们必须将主键约束定义为非聚簇。

  • Tip: Columnstore indexes are used to store large data in the columnar format, unlike the row-based storage technology. Memory-optimized table variables do not allow creating this type of indexes on it. When we try to create a columnstore index, we will get the following error提示:与基于行的存储技术不同,列存储索引用于以列格式存储大数据。 内存优化的表变量不允许在其上创建此类索引。 当我们尝试创建列存储索引时,将出现以下错误
CREATE TYPE MemoryTypeColumnStore AS TABLE
(ID INT PRIMARY KEY NONCLUSTERED,
Col1 VARCHAR(40) UNIQUE,
Col2 VARCHAR(40) NOT NULL,
Col3 int CHECK (Col3>=20),
INDEX IX01_ColumnStore CLUSTERED COLUMNSTORE
) WITH
(MEMORY_OPTIMIZED = ON
)

The statement failed because columnstore indexes are not allowed on table types and table variables

  • The statement failed because columnstore indexes are not allowed on table types and table variables. Remove the column store index specification from the table type or table variable declaration.
  • 该语句失败,因为不允许在表类型和表变量上使用列存储索引。 从表类型或表变量声明中删除列存储索引规范。

性能基准测试:内存优化的表变量与基于磁盘的表变量 (Performance benchmarking: Memory-optimized table variable vs disk-based table variables)

From the beginning of this article, we have been focusing on the performance advantages of memory-optimized table variables. In this section, we will make a performance test and compare the results of the memory-optimized and disk-based table variables. To perform this test we will use SQLQueryStress because it is very simple and handy to measure the performance result of the queries. At the same time, we will perform the following scenario in the test query.

从本文开始,我们一直专注于内存优化表变量的性能优势。 在本节中,我们将进行性能测试,并比较内存优化和基于磁盘的表变量的结果。 为了执行此测试,我们将使用SQLQueryStress,因为它非常简单且方便地测量查询的性能结果。 同时,我们将在测试查询中执行以下方案。

  • 1001 rows will be inserted to the table variables

    将1001行插入到表变量中
  • 100 rows will be deleted from the table variables

    将从表变量中删除100行
  • 200 rows of the table variable will be updated

    表变量的200行将被更新
  • The remaining rows of the table variables will be fetched by the table variables

    表变量的其余行将由表变量获取

At first, we will create the memory-optimized table type.

首先,我们将创建内存优化表类型。

CREATE TYPE TestMemTyp AS TABLE
(Id      INT
PRIMARY KEY NONCLUSTERED, 
ODate   DATETIME, 
St      TINYINT, 
SNumber NVARCHAR(25), 
ANumber NVARCHAR(15)
) WITH
(MEMORY_OPTIMIZED = ON
);

Through the following query, we will create the disk-based table type.

通过以下查询,我们将创建基于磁盘的表类型。

CREATE TYPE TestDiskTyp AS TABLE
(Id      INT
 PRIMARY KEY NONCLUSTERED, 
 ODate   DATETIME, 
 St      TINYINT, 
 SNumber NVARCHAR(25), 
 ANumber NVARCHAR(15)
)

Before we start our performance test, we will use Performance Monitor, also known as Perfmon in order to capture performance statistics of the queries. At first, we will launch the Perfmon and right-click on the performance capturing screen and select the Remove All Counters.

在开始性能测试之前,我们将使用性能监视器(也称为Perfmon )以捕获查询的性能统计信息。 首先,我们将启动Perfmon,然后在性能捕获屏幕上单击鼠标右键,然后选择“删除所有计数器”。

Remove all counters from the performance monitor

As the second step, we will click the (+) button to add new counters and add the Temp Tables Creation Rate under the SQL Server: General Statistics menu. This counter presents how many temp tables or table variables are created per second.

第二步,我们将单击( + )按钮添加新的计数器,并在“ SQL Server:常规统计信息”菜单下添加“ 临时表创建速率 ”。 该计数器显示每秒创建多少个临时表或表变量。

Add Temp Tables Creation Rate to the performance monitor

Our second counter will be Total Latch Wait Time (ms) under the SQL Server: General Statistics and it indicates total latch wait time for the last second.

我们的第二个计数器将是SQL Server:常规统计信息下的总锁存等待时间(ms),它指示最后一秒的总锁存等待时间。

Add Total Latch Wait Time (ms) to the performance monitor

Our last counter will be Batch Requests/Sec under SQL Server: SQL Statistics. This counter represents how many SQL statements received by the SQL engine. This counter solely does not indicate any problem but we will use this counter to track the activity of the server during the execution of the queries.

我们的最后一个计数器将是SQL Server:SQL Statistics下的Batch Requests / Sec 。 此计数器代表SQL引擎接收SQL语句数。 该计数器仅表示没有问题,但是我们将使用该计数器来跟踪查询执行期间服务器的活动。

Add Batch Requests/Sec to the performance monitor

Now we will start the performance test for the memory-optimized table variable using the SQLQueryStress. In the Number of Iterations box, we can define how many times the query will be executed and we will set this number as 40. The number of Threads determines how many concurrent virtual sessions will execute this query and we will set this number as 20.

现在,我们将使用SQLQueryStress对内存优化的表变量启动性能测试。 在“迭代次数”框中,我们可以定义执行查询的次数,并将此次数设置为40。“线程数”确定执行此查询的并发虚拟会话的次数,并将此次数设置为20。

DECLARE @TestMemOptVar AS TestMemTyp ;
INSERT INTO @TestMemOptVar
       SELECT SalesOrderId, 
              OrderDate, 
              STATUS, 
              SalesOrderNumber, 
              AccountNumber
       FROM Sales.SalesOrderHeader S
       WHERE DueDate <= '2011-10-26 00:00:00.000';
DELETE FROM @TestMemOptVar
WHERE Id <= 43758;
UPDATE @TestMemOptVar
  SET 
      St = 0
WHERE Id <= 43958;
SELECT *
FROM @TestMemOptVar;

Use SQLStressTest for the performance test

We will click the Database button to determine the database connection and credential settings.

我们将单击数据库按钮来确定数据库连接和凭据设置。

Database settings of the SQLStressTest

As a final step, we will click the GO button and starts the execution of the query 40 times by the 20 virtual users.

最后一步,我们将单击GO按钮,并开始由20个虚拟用户执行40次查询。

Use SQLStressTest for the memory-optimized table variable  performance test

The query took 8.643 seconds to complete. Now we will execute the same query for the disk-based table variable.

该查询花了8.643秒完成。 现在,我们将对基于磁盘的表变量执行相同的查询。

DECLARE @TestDiskOptVar AS TestDiskTyp ;
INSERT INTO @TestDiskOptVar
       SELECT SalesOrderId, 
              OrderDate, 
              STATUS, 
              SalesOrderNumber, 
              AccountNumber
       FROM Sales.SalesOrderHeader S
           WHERE 
       DueDate <= '2011-10-26 00:00:00.000';
DELETE FROM @TestDiskOptVar
WHERE Id <= 43758;
UPDATE @TestDiskOptVar
  SET 
      St = 0
WHERE Id <= 43958;
SELECT *
FROM @TestDiskOptVar;

Analyze SQLStressTest results

The query using the disk-based table variable took 13.053 seconds to complete. Also, you can see the performance monitor result in the below illustration.

使用基于磁盘的表变量的查询完成了13.053秒。 另外,您可以在下图中看到性能监视器的结果。

Analyzing the results of the Performance Monitor

This line graphic represents, SQL Server can handle more requests for the memory-optimized table variable in a shorter time than disk-based table variables. At the same time, there isn’t any latch issue occurred for it. This performance test has clearly shown us that the memory-optimized table variable performs better performance than the disk-based ones.

此线形图表示,与基于磁盘的表变量相比,SQL Server可以在更短的时间内处理更多的内存优化表变量请求。 同时,没有发生任何闩锁问题。 性能测试清楚地向我们表明,内存优化的表变量比基于磁盘的表变量具有更好的性能。

结论 (Conclusion)

In this article, we discussed the memory-optimized table variables usage details and performance benefits. This type of the variable stores data in the memory so that they don’t produce any disk I/O thus they aren’t affected by any contention or latency which may occur on the TempDB database. This working logic is the biggest advantage against disk-based table variables.

在本文中,我们讨论了内存优化的表变量的用法细节和性能优势。 这种类型的变量将数据存储在内存中,这样它们就不会产生任何磁盘I / O,因此不会受到TempDB数据库上可能发生的任何争用或延迟的影响。 这种工作逻辑是针对基于磁盘的表变量的最大优势。

翻译自: https://www.sqlshack.com/memory-optimized-table-variables-in-sql-server/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值