Linux 上 SQL Server 的性能功能演练

适用于:SQL Server - Linux

如果你是刚接触 SQL Server 的 Linux 用户,以下任务可帮助你了解某些性能功能。 虽然这些并非 Linux 独有或特定的任务,但能有助于你了解需要深入了解的领域。 每个示例中均提供了该领域的详细文档链接。

注意

下面的示例使用 AdventureWorks2022 示例数据库。 有关如何获取并安装此示例数据库的说明,请参阅将 SQL Server 数据库从 Windows 还原到 Linux

创建列存储索引

列存储索引是使用列式数据格式(称为列存储)存储和查询大量数据的技术。

  1. 通过执行以下 Transact-SQL 命令将列存储索引添加到 SalesOrderDetail 表:

    CREATE NONCLUSTERED COLUMNSTORE INDEX [IX_SalesOrderDetail_ColumnStore]
       ON Sales.SalesOrderDetail
       (UnitPrice, OrderQty, ProductID);
    GO
    
  2. 执行以下查询,使用列存储索引扫描表:

    SELECT ProductID, SUM(UnitPrice) SumUnitPrice, AVG(UnitPrice) AvgUnitPrice,
       SUM(OrderQty) SumOrderQty, AVG(OrderQty) AvgOrderQty
    FROM Sales.SalesOrderDetail
       GROUP BY ProductID
       ORDER BY ProductID;
    
  3. 查找列存储索引的 object_id,然后确认它出现在 SalesOrderDetail 表的使用情况统计信息中,以验证是否使用了列存储索引:

    SELECT * FROM sys.indexes WHERE name = 'IX_SalesOrderDetail_ColumnStore'
    GO
    
    SELECT *
    FROM sys.dm_db_index_usage_stats
       WHERE database_id = DB_ID('AdventureWorks2022')
       AND object_id = OBJECT_ID('AdventureWorks2022.Sales.SalesOrderDetail');
    

使用内存中 OLTP

SQL Server 提供的内存中 OLTP 功能可极大提升应用程序系统的性能。 本节内容将介绍如何创建存储在内存中的内存优化表,以及创建无需编译或解释即可访问表的本机编译的存储过程。

配置内存中 OLTP 的数据库

  1. 建议将数据库的兼容级别至少设置为 130,以使用内存中 OLTP。 使用以下查询检查 AdventureWorks2022 的当前兼容级别:

    USE AdventureWorks2022;
    GO
    SELECT d.compatibility_level
    FROM sys.databases as d
        WHERE d.name = DB_NAME();
    GO
    

    如有必要,将级别更新为 130:

    ALTER DATABASE CURRENT
    SET COMPATIBILITY_LEVEL = 130;
    GO
    
  2. 当事务同时涉及基于磁盘的表和内存优化表时,事务的内存优化部分必须在名为“快照”的事务隔离级别运行。 若要可靠地对跨容器事务中的内存优化表强制执行此级别,请执行以下脚本:

    ALTER DATABASE CURRENT SET MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT=ON;
    GO
    
  3. 需要先创建内存优化文件组和数据文件的容器,然后才能创建内存优化表:

    ALTER DATABASE AdventureWorks2022
       ADD FILEGROUP AdventureWorks_mod
          CONTAINS memory_optimized_data;
    GO
    ALTER DATABASE AdventureWorks2022
       ADD FILE (NAME='AdventureWorks_mod',
       FILENAME='/var/opt/mssql/data/AdventureWorks_mod')
          TO FILEGROUP AdventureWorks_mod;
    GO
    

创建内存优化表

内存优化表的主存储是主内存,因此与基于磁盘的表不同,不必从磁盘将数据读取到内存缓冲区。 若要创建内存优化表,请使用 MEMORY_OPTIMIZED = ON 子句。

  1. 执行以下查询创建内存优化表 dbo.ShoppingCart。 默认情况下,数据保留在磁盘上以获得持续性(还可将 DURABILITY 设置为仅保留架构)。

    CREATE TABLE dbo.ShoppingCart (
    ShoppingCartId INT IDENTITY(1,1) PRIMARY KEY NONCLUSTERED,
    UserId INT NOT NULL INDEX ix_UserId NONCLUSTERED HASH WITH (BUCKET_COUNT=1000000),
    CreatedDate DATETIME2 NOT NULL,
    TotalPrice MONEY
    ) WITH (MEMORY_OPTIMIZED=ON);
    GO
    
  2. 在表中插入一些记录:

    INSERT dbo.ShoppingCart VALUES (8798, SYSDATETIME(), NULL);
    INSERT dbo.ShoppingCart VALUES (23, SYSDATETIME(), 45.4);
    INSERT dbo.ShoppingCart VALUES (80, SYSDATETIME(), NULL);
    INSERT dbo.ShoppingCart VALUES (342, SYSDATETIME(), 65.4);
    

本机编译的存储过程

SQL Server 支持访问内存优化表的本机编译的存储过程。 T-SQL 语句编译为机器代码并存储为本机 DLL,能够比传统 T-SQL 更快地访问数据,更高效地执行查询。 对使用 NATIVE_COMPILATION 来标记的存储过程执行本机编译。

  1. 执行以下脚本创建本机编译的存储过程,该过程在 ShoppingCart 表中插入大量记录:

    CREATE PROCEDURE dbo.usp_InsertSampleCarts @InsertCount INT
        WITH NATIVE_COMPILATION, SCHEMABINDING AS
    BEGIN ATOMIC
        WITH (TRANSACTION ISOLATION LEVEL = SNAPSHOT, LANGUAGE = N'us_english')
    
    DECLARE @i INT = 0
    
    WHILE @i < @InsertCount
       BEGIN
           INSERT INTO dbo.ShoppingCart VALUES (1, SYSDATETIME(), NULL)
    
           SET @i += 1
       END
    END
    
  2. 插入 1,000,000 行:

    EXEC usp_InsertSampleCarts 1000000;
    
  3. 验证是否已插入这些行:

    SELECT COUNT(*) FROM dbo.ShoppingCart;
    

使用查询存储

查询存储区收集有关查询、执行计划和运行时统计信息的详细性能信息。

SQL Server 2022 (16.x) 之前,默认情况下不启用查询存储,可以使用 ALTER DATABASE 启用:

ALTER DATABASE AdventureWorks2022 SET QUERY_STORE = ON;

运行以下查询,返回查询存储中有关查询和计划的信息:

SELECT Txt.query_text_id, Txt.query_sql_text, Pl.plan_id, Qry.*
FROM sys.query_store_plan AS Pl
   JOIN sys.query_store_query AS Qry
      ON Pl.query_id = Qry.query_id
   JOIN sys.query_store_query_text AS Txt
      ON Qry.query_text_id = Txt.query_text_id;

查询动态管理视图

动态管理视图返回可用于监视服务器实例的运行状况、诊断故障以及优化性能的服务器状态信息。

要查询 dm_os_wait 统计信息动态管理视图:

SELECT wait_type, wait_time_ms
FROM sys.dm_os_wait_stats;

另请参阅