インメモリ OLTP でメモリ使用量の監視とトラブルシューティング

適用対象:SQL Server

インメモリ OLTP は、ディスク ベース テーブルとは異なるパターンでメモリを消費します。 メモリおよびガベージ コレクション サブシステムに提供される DMV またはパフォーマンス カウンターを使用して、データベース内のメモリ最適化テーブルとインデックス向けに割り当てられて使用されているメモリの量を監視できます。 これによって、システム レベルとデータベース レベルの両方で状況を表示でき、メモリの枯渇による問題を回避できます。

この記事では、SQL Server のインメモリ OLTP メモリ使用量の監視について説明します。

Note

このチュートリアルは、Azure SQL Managed Instance または Azure SQL データベースには適用されません。 代わりに、Azure SQL でインメモリ OLTP のデモについては、次を参照してください。

インメモリ OLTP 使用量の監視の詳細については、次を参照してください。

1. メモリ最適化テーブルが含まれるサンプル データベースの作成

次の手順では、練習で使用するデータベースを作成します。

  1. SQL Server Management Studio を起動します。

  2. [New Query] を選択します。

    Note

    既にメモリ最適化テーブルが含まれるデータベースがある場合、この次の手順を省略できます。

  3. このコードを新しいクエリ ウィンドウに貼り付けて各セクションを実行し、この練習である IMOLTP_DB のテスト データベースを作成します。

    -- create a database to be used  
    CREATE DATABASE IMOLTP_DB  
    GO
    
  4. 以下のサンプル スクリプトでは C:\Data を使用していますが、インスタンスはデータベースのデータ ファイルに異なるフォルダーの場所を使用している可能性があります。 インメモリのファイル場所に適切な場所を使用するため、次のスクリプトを更新して実行します。

    ALTER DATABASE IMOLTP_DB ADD FILEGROUP IMOLTP_DB_xtp_fg CONTAINS MEMORY_OPTIMIZED_DATA  
    ALTER DATABASE IMOLTP_DB ADD FILE( NAME = 'IMOLTP_DB_xtp' , FILENAME = 'C:\Data\IMOLTP_DB_xtp') TO FILEGROUP IMOLTP_DB_xtp_fg;  
    GO
    
  5. 次のスクリプトは、このトピックの残りのセクションで使用できる 3 つのメモリ最適化テーブルを作成します。 例では、メモリ最適化テーブルで使用できるメモリの量を制御できるように、データベースをリソース プールにマップしました。 IMOLTP_DB データベースで次のスクリプトを実行します。

    -- create some tables  
    USE IMOLTP_DB  
    GO  
    
    -- create the resoure pool  
    CREATE RESOURCE POOL PoolIMOLTP WITH (MAX_MEMORY_PERCENT = 60);  
    ALTER RESOURCE GOVERNOR RECONFIGURE;  
    GO  
    
    -- bind the database to a resource pool  
    EXEC sp_xtp_bind_db_resource_pool 'IMOLTP_DB', 'PoolIMOLTP'  
    
    -- you can query the binding using the catalog view as described here  
    SELECT d.database_id  
         , d.name  
         , d.resource_pool_id  
    FROM sys.databases d  
    GO  
    
    -- take database offline/online to finalize the binding to the resource pool  
    USE master  
    GO  
    
    ALTER DATABASE IMOLTP_DB SET OFFLINE  
    GO  
    ALTER DATABASE IMOLTP_DB SET ONLINE  
    GO  
    
    -- create some tables  
    USE IMOLTP_DB  
    GO  
    
    -- create table t1  
    CREATE TABLE dbo.t1 (  
           c1 int NOT NULL CONSTRAINT [pk_t1_c1] PRIMARY KEY NONCLUSTERED  
         , c2 char(40) NOT NULL  
         , c3 char(8000) NOT NULL  
         ) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)  
    GO  
    
    -- load t1 150K rows  
    DECLARE @i int = 0  
    BEGIN TRAN  
    WHILE (@i <= 150000)  
       BEGIN  
          INSERT t1 VALUES (@i, 'a', replicate ('b', 8000))  
          SET @i += 1;  
       END  
    Commit  
    GO  
    
    -- Create another table, t2  
    CREATE TABLE dbo.t2 (  
           c1 int NOT NULL CONSTRAINT [pk_t2_c1] PRIMARY KEY NONCLUSTERED  
         , c2 char(40) NOT NULL  
         , c3 char(8000) NOT NULL  
         ) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)  
    GO  
    
    -- Create another table, t3   
    CREATE TABLE dbo.t3 (  
           c1 int NOT NULL CONSTRAINT [pk_t3_c1] PRIMARY KEY NONCLUSTERED HASH (c1) WITH (BUCKET_COUNT = 1000000)  
         , c2 char(40) NOT NULL  
         , c3 char(8000) NOT NULL  
         ) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA)  
    GO  
    

2. メモリ使用量の監視

SQL Server Management Studio でメモリ使用量を監視する

SQL Server 2014 (12.x)以降、インメモリ テーブルが消費するメモリを監視するため、SQL Server Management Studio はビルトインの標準レポートがあります。 オブジェクト エクスプローラーを使用してこれらのレポートにアクセスできます。 オブジェクト エクスプローラーを使用すると、個々のメモリ最適化テーブルで消費されるメモリも監視できます。

データベース レベルでの消費量

次のように、データベース レベルでのメモリ使用を監視できます。

  1. SQL Server Management Studio を起動し、SQL Server または SQL Managed Instance に接続します。

  2. オブジェクト エクスプローラーで、レポートが必要なデータベースを右クリックします。

  3. コンテキスト メニューで、[レポート] ->[標準レポート] ->[メモリ最適化オブジェクトによるメモリ使用量]の順にクリックします。

Screenshot showing the Object Explorer with Reports > Standard Reports > Memory Usage By Memory Optimized Objects selected.

このレポートは、上で作成したデータベースによるメモリ消費を示します。

Screenshot of the Total Memory Usage By Memory Optimized Objects report.

DMV でメモリ使用量を監視する

メモリ最適化テーブル、インデックス、システム オブジェクト、およびランタイム構造によって消費されるメモリを監視するために、多くの DMV を使用できます。

メモリ最適化テーブルおよびインデックスによるメモリ消費

次に示すように、 sys.dm_db_xtp_table_memory_stats にクエリを実行することで、すべてのユーザー テーブル、インデックス、およびシステム オブジェクトのメモリ消費を確認できます。

SELECT object_name(object_id) AS [Name]
     , *  
   FROM sys.dm_db_xtp_table_memory_stats;

サンプル出力

Name       object_id   memory_allocated_for_table_kb memory_used_by_table_kb memory_allocated_for_indexes_kb memory_used_by_indexes_kb  
---------- ----------- ----------------------------- ----------------------- ------------------------------- -------------------------  
t3         629577281   0                             0                       128                             0  
t1         565577053   1372928                       1200008                 7872                            1942  
t2         597577167   0                             0                       128                             0  
NULL       -6          0                             0                       2                               2  
NULL       -5          0                             0                       24                              24  
NULL       -4          0                             0                       2                               2  
NULL       -3          0                             0                       2                               2  
NULL       -2          192                           25                      16                              16  

詳細については、「sys.dm_db_xtp_table_memory_stats」 を参照してください。

内部システム構造によるメモリ消費

メモリは、トランザクション構造、データ ファイルとデルタ ファイルのバッファー、ガベージ コレクション構造などのシステム オブジェクトによっても消費されます。 次に示すように、 sys.dm_xtp_system_memory_consumers にクエリを実行することで、これらのシステム オブジェクトに使用されるメモリを確認できます。

SELECT memory_consumer_desc  
     , allocated_bytes/1024 AS allocated_bytes_kb  
     , used_bytes/1024 AS used_bytes_kb  
     , allocation_count  
   FROM sys.dm_xtp_system_memory_consumers  

サンプル出力

memory_consumer_ desc allocated_bytes_kb   used_bytes_kb        allocation_count  
------------------------- -------------------- -------------------- ----------------  
VARHEAP                   0                    0                    0  
VARHEAP                   384                  0                    0  
DBG_GC_OUTSTANDING_T      64                   64                   910  
ACTIVE_TX_MAP_LOOKAS      0                    0                    0  
RECOVERY_TABLE_CACHE      0                    0                    0  
RECENTLY_USED_ROWS_L      192                  192                  261  
RANGE_CURSOR_LOOKSID      0                    0                    0  
HASH_CURSOR_LOOKASID      128                  128                  455  
SAVEPOINT_LOOKASIDE       0                    0                    0  
PARTIAL_INSERT_SET_L      192                  192                  351  
CONSTRAINT_SET_LOOKA      192                  192                  646  
SAVEPOINT_SET_LOOKAS      0                    0                    0  
WRITE_SET_LOOKASIDE       192                  192                  183  
SCAN_SET_LOOKASIDE        64                   64                   31  
READ_SET_LOOKASIDE        0                    0                    0  
TRANSACTION_LOOKASID      448                  448                  156  
PGPOOL:256K               768                  768                  3  
PGPOOL: 64K               0                    0                    0  
PGPOOL:  4K               0                    0                    0  

詳細については、「sys.dm_xtp_system_memory_consumers)」を参照してください。

メモリ最適化テーブルにアクセスするときの実行時のメモリ消費

次のクエリを使用して、プロシージャ キャッシュなどのランタイム構造で消費されたメモリを確認できます。このクエリを実行して、プロシージャ キャッシュ用などのランタイム構造で使用されたメモリの情報を取得します。 すべてのランタイム構造は XTP でタグ付けされます。

SELECT memory_object_address  
     , pages_in_bytes  
     , bytes_used  
     , type  
   FROM sys.dm_os_memory_objects WHERE type LIKE '%xtp%'  

サンプル出力

memory_object_address pages_ in_bytes bytes_used type  
--------------------- ------------------- ---------- ----  
0x00000001F1EA8040    507904              NULL       MEMOBJ_XTPDB  
0x00000001F1EAA040    68337664            NULL       MEMOBJ_XTPDB  
0x00000001FD67A040    16384               NULL       MEMOBJ_XTPPROCCACHE  
0x00000001FD68C040    16384               NULL       MEMOBJ_XTPPROCPARTITIONEDHEAP  
0x00000001FD284040    16384               NULL       MEMOBJ_XTPPROCPARTITIONEDHEAP  
0x00000001FD302040    16384               NULL       MEMOBJ_XTPPROCPARTITIONEDHEAP  
0x00000001FD382040    16384               NULL       MEMOBJ_XTPPROCPARTITIONEDHEAP  
0x00000001FD402040    16384               NULL       MEMOBJ_XTPPROCPARTITIONEDHEAP  
0x00000001FD482040    16384               NULL       MEMOBJ_XTPPROCPARTITIONEDHEAP  
0x00000001FD502040    16384               NULL       MEMOBJ_XTPPROCPARTITIONEDHEAP  
0x00000001FD67E040    16384               NULL       MEMOBJ_XTPPROCPARTITIONEDHEAP  
0x00000001F813C040    8192                NULL       MEMOBJ_XTPBLOCKALLOC  
0x00000001F813E040    16842752            NULL       MEMOBJ_XTPBLOCKALLOC  

詳細については、「sys.dm_os_memory_objects (Transact-SQL)」を参照してください。

インスタンス全体でインメモリ OLTP エンジンによって消費されるメモリ

インメモリ OLTP エンジンとメモリ最適化オブジェクトに割り当てられたメモリは、SQL Server インスタンス内の他のメモリ コンシューマーと同様に管理されます。 MEMORYCLERK_XTP 型のクラークによって、インメモリ OLTP エンジンに割り当てられたすべてのメモリについて確認できます。 次のクエリを使用して、インメモリ OLTP エンジンによって使用されるすべてのメモリを確認します。

-- This DMV accounts for all memory used by the in-memory engine  
SELECT type  
   , name  
   , memory_node_id  
   , pages_kb/1024 AS pages_MB   
   FROM sys.dm_os_memory_clerks WHERE type LIKE '%xtp%'  

次のサンプル出力では、割り当てられたメモリはシステム レベルのメモリが 18 MB で、1358 MB が割り当てられた database_id が 5 であることを示しています。 このデータベースは専用のリソース プールにマップされるため、このメモリはそのリソース プールに反映されます。

type                 name       memory_node_id pages_MB  
-------------------- ---------- -------------- --------------------  
MEMORYCLERK_XTP      Default    0              18  
MEMORYCLERK_XTP      DB_ID_5    0              1358  
MEMORYCLERK_XTP      Default    64             0  

詳しくは、sys.dm_os_memory_clerks に関する記事をご覧ください。

3. メモリ最適化オブジェクトが消費するメモリの管理

メモリ最適化テーブルを名前付きリソース共有元にバインディングすることにより、メモリ最適化テーブルが消費するメモリの合計を管理できます。 詳細については、「メモリ最適化テーブルを備えたデータベースをリソース共有元にバインディングする」を参照してください。

メモリの問題のトラブルシューティング

メモリに関する問題のトラブルシューティングは、次の 3 つの手順で行います。

  1. データベースまたはインスタンスのオブジェクトによって消費されているメモリ量を特定します。 前に説明したように、メモリ最適化テーブルで使用可能な豊富な監視ツール セットを使用できます。 たとえば、sys.dm_db_xtp_table_memory_stats または sys.dm_os_memory_clerks の DMV のサンプル クエリを参照してください。

  2. メモリ消費がどのように拡大し、どれぐらいの余裕が残されているかを確認します。 メモリ消費を定期的に監視することで、メモリの使用がどのように拡大しているかを確認できます。 たとえば、名前付きリソース プールにデータベースをマップしている場合は、パフォーマンス カウンターの Used Memory (KB) を監視して、メモリの使用量がどのように拡大しているかを確認することができます。

  3. 発生する可能性があるメモリの問題を軽減するアクションを実行します。 詳細については、「メモリ不足の問題の解決」を参照してください。