インメモリ OLTP の概要と使用シナリオ

適用対象:SQL ServerAzure SQL DatabaseAzure SQL Managed Instance

インメモリ OLTP は、トランザクション処理のパフォーマンスの最適化、データの取り込み、データの読み込み、および一時的なデータのシナリオに SQL Server と Azure SQL Database で使用できる最高級の技術です。 この記事では、インメモリ OLTP のテクノロジと使用シナリオの概要について説明します。 この情報を参照して、インメモリ OLTP が用途に合っているかどうかを判断してください。 この記事の最後には、インメモリ OLTP オブジェクトを表示する例、パフォーマンス デモの参照、次のステップに使用できるリソースの参照を掲載しています。

インメモリ OLTP の概要

インメモリ OLTP は、適切なワークロードの場合にパフォーマンスが大きく向上します。 一部の事例では、最大 30 倍のパフォーマンス向上が見られていますが、向上率はワークロードによって変わります。

それでは、このパフォーマンス向上は何に由来するのでしょうか。 基本的に、インメモリ OLTP は、データ アクセスとトランザクションの実行を効率化し、同時に実行されるトランザクション間のロックとラッチの競合を取り除くことで、トランザクション プロセスのパフォーマンスを改善します。 インメモリ OLTP が高速な理由はメモリ内にあるためではなく、メモリ内のデータを中心にして最適化されているためです。 メモリ内のコンカレンシー処理が多い計算に関する最新の機能強化を利用するように、データ ストレージ、アクセス、処理アルゴリズムはゼロから再設計されました。

現在では、データがメモリ内にあるからというだけで、障害が発生したときにデータが失われることを意味しなくなりました。 既定では、すべてのトランザクションは完全に持続可能であり、SQL Server のその他のテーブルと同じ持続性の保証があります。トランザクション コミットの一部として、すべての変更はディスク上のトランザクション ログに書き込まれます。 トランザクション コミット後のどこかの時点で障害が発生すると、データベースがオンラインに戻ったときに、コミットされたデータを利用できます。 さらに、インメモリ OLTP は、可用性グループフェールオーバー クラスター インスタンス、バックアップ/復元など、SQL Server の高可用性とディザスター リカバリー機能すべてと連携して動作します。

データベースでインメモリ OLTP を使用するには、次に示すオブジェクトの種類から 1 つまたは複数使用します。

  • メモリ最適化テーブル は、ユーザー データの格納に使用されます。 テーブルは、作成時にメモリが最適化されるように宣言します。
  • 非持続的テーブル は、キャッシュまたは中間の結果セット用の一時的なデータに使用されます (従来の一時テーブルは置き換えられます)。 非持続的テーブルは、DURABILITY=SCHEMA_ONLY を使用して宣言されるメモリ最適化テーブルです。つまり、これらのテーブルを変更しても、IO は発生しません。 そのため、持続性が重要ではない場合、ログ IO リソースの消費を回避することができます。
  • メモリ最適化テーブル型は、テーブル値パラメーター(TVP)とストアド プロシージャの中間結果セットに使用されます。 メモリ最適化テーブル型は、従来のテーブル型の代わりに使用できます。 メモリ最適化テーブル型を使用して宣言したテーブル変数と TVP は、非持続的メモリ最適化テーブルの利点 (効率的なデータ アクセス、IO なし) を継承します。
  • ネイティブ コンパイル T-SQL モジュール は、操作の処理に必要な CPU サイクルを減らして、個々のトランザクションにかかる時間をさらに短縮するために使用されます。 Transact-SQL モジュールは、作成時にネイティブでコンパイルするように宣言します。 このとき、ストアド プロシージャ、トリガー、スカラー ユーザー定義関数という T-SQL モジュールをネイティブでコンパイルできます。

インメモリ OLTP は SQL Server と SQL Database に組み込まれています。 これらのオブジェクトは、従来の対応するオブジェクトに似た方法で動作でするため、多くの場合、データベースとアプリケーションの変更を最小限に抑えながらパフォーマンスを向上できます。 さらに、同じデータベースにメモリ最適化テーブルと従来のディスクベースのテーブルの両方を持ち、2 つのテーブルに対してクエリを実行することができます。 この記事の後半で、これらのオブジェクトの種類ごとに「Transact-SQL スクリプトのサンプル」を参照してください。

インメモリ OLTP の使用シナリオ

インメモリ OLTP は魔法の高速化ボタンではなく、あらゆるワークロードに適しているわけではありません。 たとえば、ほとんどのクエリが広範囲に及ぶデータに対する集計を行う場合、メモリ最適化テーブルで CPU 使用率は下がりません。 このようなシナリオには、列ストア インデックスが役立ちます。

注意

既知の問題点: メモリ最適化テーブルを含むデータベースでは、回復なしでトランザクション ログ バックアップを実行し、後で回復を使用してトランザクション ログの回復を実行すると、データベースの復元プロセスが応答しなくなる可能性があります。 この問題点は、ログ配布機能にも影響する可能性があります。 この問題を回避するには、復元プロセスを開始する前に SQL Server インスタンスを再起動します。

次に、顧客がインメモリ OLTP で成功したシナリオとアプリケーション パターンの一覧を紹介します。

高スループット、低遅延トランザクションの処理

これはインメモリ OLTP を構築する中核となるシナリオです。個々のトランザクションの低遅延を保ちながら、大量のトランザクションに対応します。

一般的なワークロード シナリオとして、金融商品の取引、スポーツくじ、モバイル ゲーム、広告配信などがあります。 別の一般的なパターンには、読み取りや更新が頻繁に行われる"カタログ"もあります。 たとえば、大きなファイルを複数のクラスターノードに分散して配置し、各ファイルのシャードの位置をメモリ最適化テーブルでカタログ化するような場合です。

実装の考慮事項

中核となるトランザクション テーブル、つまり、最もパフォーマンスが重要なトランザクションがあるテーブルにメモリ最適化テーブルを使用します。 ネイティブでコンパイルされたストアド プロシージャを使用して、ビジネス トランザクションに関連付けられたロジックの実行を最適化します。 データベースのストアド プロシージャに組み込むことができるロジック数が多いほど、インメモリ OLTP の利点も大きくなります。

既存のアプリケーションで開始するには:

  1. トランザクション パフォーマンス分析レポートを使用して移行するオブジェクトを特定します。
  2. 移行には、メモリ最適化アドバイザーおよびネイティブ コンパイル アドバイザーを使用します。

IoT (モノのインターネット) などのデータ統合

インメモリ OLTP は、同時にさまざまなソースから大量のデータを取り込む処理が特に得意です。 また、多くの場合、他の取り込み先と比較して、SQL Server データベースにデータを取り込む方が利点があります。これは、SQL Server ではデータに対するクエリの実行速度が速く、リアルタイムで分析情報が得られるためです。

一般的なアプリケーション パターン:

  • センサーの読み取りとイベントを取り込みます。通知だけでなく履歴分析を可能にします。
  • 複数のソースからでも、一括更新を管理し、同時読み取りのワークロードに対する影響を最小限に抑えることができます。

実装の考慮事項

データの取り込みにメモリ最適化テーブルを使用します。 取り込みの大部分が (更新ではなく) 挿入で構成され、データのインメモリ OLTP ストレージの占有領域が重要な場合、次のいずれかを行います。

  • INSERT INTO <disk-based table> SELECT FROM <memory-optimized table> を実行するジョブを使用して、クラスター化列ストア インデックスを持つディスクベースのテーブルにデータを定期的にバッチ オフロードします。または、
  • 一時メモリ最適化テーブルを使用して、履歴データを管理します。このモードでは、履歴データはディスクに保存され、データの移動はシステムによって管理されます。

SQL Server サンプル リポジトリに一時メモリ最適化テーブル、メモリ最適化テーブル型、およびネイティブ コンパイル ストアド プロシージャを使用するスマート グリッド アプリケーション含めることでデータの取り込みを高速化し、センサー データのインメモリ OLTP ストレージの占有領域を管理しています。

キャッシュとセッションの状態

インメモリ OLTP テクノロジを使用すると、SQL Server または Azure SQL データベースのデータベース エンジンは、セッション状態を維持したり (ASP.NET アプリケーションの場合など)、キャッシュを行ったりするための魅力的なプラットフォームになります。

ASP.NET セッションの状態は、インメモリ OLTP で成功している使用事例です。 SQL Server では、あるお客様が毎秒約 120 万要求を達成しました。 一方、社内のすべての中間層アプリケーションのキャッシュ ニーズにインメモリ OLTP を使用し始めました。 詳細については、「 How bwin is using SQL Server 2016 (13.x) In-Memory OLTP to achieve unprecedented performance and scale」(bwin が SQL Server 2016 (13.x) のインメモリ OLTP を使用して前例のないパフォーマンスとスケールを達成した方法) を参照してください。

実装の考慮事項

varbinary(max) 列に BLOB を格納することで、簡易なキーと値のストアとして非持続的メモリ最適化テーブルを使用できます。 または、SQL Server および SQL Database で JSON のサポート で半構造化キャッシュを実装できます。 最後に、多様なデータ型と制約を含み、完全なリレーショナル スキーマを使用する非持続的なテーブルで、完全なリレーショナル キャッシュを作成できます。

ASP.NET セッションの状態のメモリ最適化を始めるには、GitHub で公開されているスクリプトを使用して、組み込みの SQL Server セッションの状態プロバイダーで作成されるオブジェクトを置き換えます: aspnet-session-state

Customer case study (お客様のケース スタディ)

tempdb オブジェクトの置き換え

非持続的テーブルとメモリ最適化テーブル型を使用して、一時テーブル、テーブル変数、テーブル値パラメーター (TVP) など、従来の tempdb ベース構造を置き換えます。

メモリ最適化テーブル変数と非持続的テーブルは、従来のテーブル変数と #temp テーブルと比較すると、一般的に CPU が減り、ログの IO が完全になくなります。

実装の考慮事項

開始するには、「メモリ最適化を使用して一時テーブルとテーブル変数のパフォーマンスの向上」を参照してください。

Customer case study (お客様のケース スタディ)

ETL (抽出、変換、読み込み)

多くの場合、ETL ワークフローには、データのステージング テーブルへの読み込み、データの変換、最終的なテーブルへの読み込みが含まれています。

データのステージングには非持続的メモリ最適化テーブルを使用します。 すべての IO が完全になくなり、データ アクセスがより効率的になります。

実装の考慮事項

ワークフローの一部としてステージング テーブルで変換を実行する場合、ネイティブ コンパイル ストアド プロシージャを使用すると、変換を高速化できます。 このような変換を並列して実行できると、メモリ最適化からさらにスケール メリットが得られます。

サンプル スクリプト

インメモリ OLTP の使用を開始する前に、MEMORY_OPTIMIZED_DATA ファイルグループを作成する必要があります。 さらに、データベース互換性レベル 130 (以上) を使用し、データベース オプション MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT をオンに設定することをお勧めします。

次の場所のスクリプトを使用して、既定のデータ フォルダーにファイルグループを作成し、推奨される設定を構成できます。

次に、データベースで作成できるインメモリ OLTP オブジェクトを説明するためのサンプルのスクリプトを示します。

まず、インメモリ OLTP 用にデータベースを構成することから始めます。

-- configure recommended DB option
ALTER DATABASE CURRENT SET MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT=ON;
GO

異なる持続性を持つテーブルを作成します。

-- memory-optimized table
CREATE TABLE dbo.table1
( c1 INT IDENTITY PRIMARY KEY NONCLUSTERED,
  c2 NVARCHAR(MAX))
WITH (MEMORY_OPTIMIZED=ON);
GO
-- non-durable table
CREATE TABLE dbo.temp_table1
( c1 INT IDENTITY PRIMARY KEY NONCLUSTERED,
  c2 NVARCHAR(MAX))
WITH (MEMORY_OPTIMIZED=ON,
      DURABILITY=SCHEMA_ONLY);
GO

インメモリ テーブルとしてテーブル型を作成します。

-- memory-optimized table type
CREATE TYPE dbo.tt_table1 AS TABLE
( c1 INT IDENTITY,
  c2 NVARCHAR(MAX),
  is_transient BIT NOT NULL DEFAULT (0),
  INDEX ix_c1 HASH (c1) WITH (BUCKET_COUNT=1024))
WITH (MEMORY_OPTIMIZED=ON);
GO

ネイティブ コンパイル ストアド プロシージャを作成します。 詳細については、「データ アクセス アプリケーションからのネイティブ コンパイル ストアド プロシージャの呼び出し」を参照してください。

-- natively compiled stored procedure
CREATE PROCEDURE dbo.usp_ingest_table1
  @table1 dbo.tt_table1 READONLY
WITH NATIVE_COMPILATION, SCHEMABINDING
AS
BEGIN ATOMIC
    WITH (TRANSACTION ISOLATION LEVEL=SNAPSHOT,
          LANGUAGE=N'us_english')

  DECLARE @i INT = 1

  WHILE @i > 0
  BEGIN
    INSERT dbo.table1
    SELECT c2
    FROM @table1
    WHERE c1 = @i AND is_transient=0

    IF @@ROWCOUNT > 0
      SET @i += 1
    ELSE
    BEGIN
      INSERT dbo.temp_table1
      SELECT c2
      FROM @table1
      WHERE c1 = @i AND is_transient=1

      IF @@ROWCOUNT > 0
        SET @i += 1
      ELSE
        SET @i = 0
    END
  END

END
GO
-- sample execution of the proc
DECLARE @table1 dbo.tt_table1;
INSERT @table1 (c2, is_transient) VALUES (N'sample durable', 0);
INSERT @table1 (c2, is_transient) VALUES (N'sample non-durable', 1);
EXECUTE dbo.usp_ingest_table1 @table1=@table1;
SELECT c1, c2 from dbo.table1;
SELECT c1, c2 from dbo.temp_table1;
GO