Sql Server内存优化表-与临时表相比性能较差

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Sql Server内存优化表-与临时表相比性能较差相关的知识,希望对你有一定的参考价值。

我正在尝试使用经典临时表对Microsoft Sql Server 2016中的内存优化表进行基准测试。

SQL版本:Microsoft SQL Server 2016(SP2)(KB4052908)-13.0.5026.0(X64)2018年3月18日09:11:49版权所有(c)Windows 10 Enterprise 10.0(内部版本上的Microsoft Corporation Developer Edition(64位) 17134:)(系统管理程序)

我正在执行以下描述的步骤:https://docs.microsoft.com/en-us/sql/relational-databases/in-memory-oltp/faster-temp-table-and-table-variable-by-using-memory-optimization?view=sql-server-ver15

CrudTest_TempTable 1000, 100, 100
go 1000

CrudTest_memopt_hash 1000, 100, 100
go 1000

此测试的作用是什么?

  • 1000个插入
  • 100次随机更新
  • 100次随机删除

并且重复1000次。

使用经典临时表的第一个存储过程大约需要6秒钟才能运行。

第二个存储过程至少需要15秒,通常会出错:

Beginning execution loop
Msg 3998, Level 16, State 1, Line 3
Uncommittable transaction is detected at the end of the batch. The transaction is rolled back.
The statement has been terminated.
Msg 701, Level 17, State 103, Procedure CrudTest_memopt_hash, Line 16 [Batch Start Line 2]
There is insufficient system memory in resource pool 'default' to run this query.

我已经进行了以下优化(在更糟之前):

  • 哈希索引同时包含Col1和SpidFilter

  • <<
  • 我正在生成随机ID-没有它的每次迭代记录都记录在相同的存储桶中

  • 由于我的结果很糟糕,所以我还没有创建本地编译的SP。
  • 我的包装盒上有很多可用的RAM,SQL Server可以使用它-在不同的情况下,它分配了很多内存,但是在此测试用例中,它只是出错了。

对我来说,这些结果意味着内存优化表无法替换临时表。您是否有类似结果,还是我做错了?

使用临时表的代码是:

SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO DROP PROCEDURE IF EXISTS CrudTest_TempTable; GO CREATE PROCEDURE CrudTest_TempTable @InsertsCount int, @UpdatesCount int, @DeletesCount int AS BEGIN SET NOCOUNT ON; BEGIN TRAN; CREATE TABLE #tempTable ( Col1 INT NOT NULL PRIMARY KEY CLUSTERED, Col2 NVARCHAR(4000), Col3 NVARCHAR(4000), Col4 DATETIME2, Col5 INT NOT NULL ); DECLARE @cnt INT = 0; DECLARE @currDate DATETIME2 = GETDATE(); WHILE @cnt < @InsertsCount BEGIN INSERT INTO #tempTable (Col1, Col2, Col3, Col4, Col5) VALUES (@cnt, 'sdkfjsdjfksjvnvsanlknc kcsmksmk ms mvskldamvks mv kv al kvmsdklmsdkl mal mklasdmf kamfksam kfmasdk mfksamdfksafeowa fpmsad lak', 'msfkjweojfijm skmcksamepi eisjfi ojsona npsejfeji a piejfijsidjfai spfdjsidjfkjskdja kfjsdp fiejfisjd pfjsdiafjisdjfipjsdi s dfipjaiesjfijeasifjdskjksjdja sidjf pajfiaj pfsdj pidfe', @currDate, 100); SET @cnt = @cnt + 1; END SET @cnt = 0; WHILE @cnt < @UpdatesCount BEGIN UPDATE #tempTable SET Col5 = 101 WHERE Col1 = cast ((rand() * @InsertsCount) as int); SET @cnt = @cnt + 1; END SET @cnt = 0; WHILE @cnt < @DeletesCount BEGIN DELETE FROM #tempTable WHERE Col1 = cast ((rand() * @InsertsCount) as int); SET @cnt = @cnt + 1; END COMMIT; END GO

在内存中测试中使用的对象是:

DROP PROCEDURE IF EXISTS CrudTest_memopt_hash;
GO

DROP SECURITY POLICY IF EXISTS tempTable_memopt_hash_SpidFilter_Policy;
GO

DROP TABLE IF EXISTS tempTable_memopt_hash;
GO

DROP FUNCTION IF EXISTS fn_SpidFilter;
GO

CREATE FUNCTION fn_SpidFilter(@SpidFilter smallint)  
    RETURNS TABLE  
    WITH SCHEMABINDING , NATIVE_COMPILATION  
AS  
    RETURN  
        SELECT 1 AS fn_SpidFilter  
            WHERE @SpidFilter = @@spid;
GO

CREATE TABLE tempTable_memopt_hash  
(  
    Col1 INT NOT NULL,
    Col2 NVARCHAR(4000),
    Col3 NVARCHAR(4000),
    Col4 DATETIME2,
    Col5 INT NOT NULL,

    SpidFilter  SMALLINT    NOT NULL   DEFAULT (@@spid),  
    INDEX ix_SpidFiler NONCLUSTERED (SpidFilter), 
    INDEX ix_hash HASH (Col1, SpidFilter) WITH (BUCKET_COUNT=100000),
    CONSTRAINT CHK_SpidFilter CHECK ( SpidFilter = @@spid )
) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_ONLY);
GO


CREATE SECURITY POLICY tempTable_memopt_hash_SpidFilter_Policy  
    ADD FILTER PREDICATE dbo.fn_SpidFilter(SpidFilter)  
    ON dbo.tempTable_memopt_hash  
    WITH (STATE = ON); 
GO

使用它们的存储过程为:

CREATE PROCEDURE CrudTest_memopt_hash @InsertsCount int, @UpdatesCount int, @DeletesCount int
AS
BEGIN

    SET NOCOUNT ON;
    BEGIN TRAN;

    DECLARE @cnt INT = 0;
    DECLARE @currDate DATETIME2 = GETDATE();

    DECLARE @IdxStart INT = CAST ((rand() * 1000) AS INT);

    WHILE @cnt < @InsertsCount
    BEGIN
        INSERT INTO tempTable_memopt_hash(Col1, Col2, Col3, Col4, Col5)
        VALUES (@IdxStart + @cnt, 
        'sdkfjsdjfksjvnvsanlknc kcsmksmk ms mvskldamvks mv kv al kvmsdklmsdkl mal mklasdmf kamfksam kfmasdk mfksamdfksafeowa fpmsad lak',
        'msfkjweojfijm  skmcksamepi  eisjfi ojsona npsejfeji a piejfijsidjfai  spfdjsidjfkjskdja kfjsdp fiejfisjd pfjsdiafjisdjfipjsdi s dfipjaiesjfijeasifjdskjksjdja sidjf pajfiaj pfsdj pidfe',
        @currDate, 100);

        SET @cnt = @cnt + 1;
    END
    SET @cnt = 0;

    WHILE @cnt < @UpdatesCount
    BEGIN
        UPDATE tempTable_memopt_hash SET Col5 = 101 WHERE Col1 = @IdxStart + cast ((rand() * @InsertsCount) as int);

        SET @cnt = @cnt + 1;
    END
    SET @cnt = 0;

    WHILE @cnt < @DeletesCount
    BEGIN
        DELETE FROM tempTable_memopt_hash WHERE Col1 = @IdxStart + cast ((rand() * @InsertsCount) as int);

        SET @cnt = @cnt + 1;
    END

    DELETE FROM tempTable_memopt_hash;
    COMMIT;
END
GO

索引统计:

table   index   total_bucket_count  empty_bucket_count  empty_bucket_percent    avg_chain_length    max_chain_length
[dbo].[tempTable_memopt_hash]   PK__tempTabl__3ED0478731BB5AF0  131072  130076  99  1   3

我正在尝试使用经典临时表对Microsoft Sql Server 2016中的内存优化表进行基准测试。 SQL版本:Microsoft SQL Server 2016(SP2)(KB4052908)-2018年3月18日13.0.5026.0(X64)...

答案
首先,这类表是lock-and-latch free,这意味着您的update /insert/ delete完全不取locks,从而允许同时更改这些tables

以上是关于Sql Server内存优化表-与临时表相比性能较差的主要内容,如果未能解决你的问题,请参考以下文章

SQL server 查看什么语句在使用临时表

SQL Server进阶表表达式

在某些情况下,为什么CTE(公用表表达式)与SQL Server中的临时表相比会减慢查询速度

sql server 临时表占用硬盘吗?

MySQL5.7性能优化系列——SQL语句优化——使用物化策略优化子查询

SQL Server SQL性能优化之--pivot行列转换减少扫描计数优化查询语句