SQL Server 2014 CTP2 インメモリ OLTP...

58
SQL Server 2014 CTP2 インメモリ OLTP 機能の概要 SQL Server 技術記事 執筆者: Kalen Delaneyy 技術校閲者: Kevin Liu、Sunil Agarwal、Jos de Bruijn、Kevin Farlee、Mike Zwilling、Craig Freedman、Mike Weiner、Cristian Diaconu、Pooja Harjani、Paul Larson、David Schwartz、 Darmadi Komo 発行日: 2013 年 10 月 対象: SQL Server 2014 CTP2 概要: インメモリ OLTP (プロジェクト Hekaton) は、SQL Server に完全に統合された新しいデータベース エンジ ン コンポーネントで、メモリ常駐データにアクセスする OLTP のワークロード向けに最適化されています。インメモ リ OLTP によって、OLTP のワークロードでの大幅なパフォーマンスの向上と処理時間の低減が実現します。 テーブルを メモリ最適化テーブルとして宣言することにより、インメモリ OLTP の機能を可能にすることができま す。メモリ最適化テーブルは完全にトランザクショナルで、Transact-SQL を使用してアクセスできます。 Transact-SQL のストアド プロシージャをマシン語コードにコンパイルして、メモリ最適化テーブルのパフォーマン スをさらに向上させることができます。エンジンは高い同時実行性を持つように設計されていて、ブロックは最小 限です。

Transcript of SQL Server 2014 CTP2 インメモリ OLTP...

Page 1: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

SQL Server 2014 CTP2インメモリ OLTP機能の概要

SQL Server 技術記事

執筆者: Kalen Delaneyy

技術校閲者: Kevin Liu、Sunil Agarwal、Jos de Bruijn、Kevin Farlee、Mike Zwilling、Craig

Freedman、Mike Weiner、Cristian Diaconu、Pooja Harjani、Paul Larson、David Schwartz、

Darmadi Komo

発行日: 2013 年 10 月

対象: SQL Server 2014 CTP2

概要:

インメモリ OLTP (プロジェクト “Hekaton”) は、SQL Server に完全に統合された新しいデータベース エンジ

ン コンポーネントで、メモリ常駐データにアクセスする OLTP のワークロード向けに最適化されています。インメモ

リ OLTP によって、OLTP のワークロードでの大幅なパフォーマンスの向上と処理時間の低減が実現します。

テーブルを “メモリ最適化テーブル” として宣言することにより、インメモリ OLTP の機能を可能にすることができま

す。メモリ最適化テーブルは完全にトランザクショナルで、Transact-SQL を使用してアクセスできます。

Transact-SQL のストアド プロシージャをマシン語コードにコンパイルして、メモリ最適化テーブルのパフォーマン

スをさらに向上させることができます。エンジンは高い同時実行性を持つように設計されていて、ブロックは最小

限です。

Page 2: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

2

著作権

このドキュメントは現状有姿で提供され、 このドキュメントに記載されている情報や見解 (URL 等のインター

ネット Web サイトに関する情報を含む) は、将来予告なしに変更されることがあります。 お客様は、その使用

に関するリスクを負うものとします。

このドキュメントは、Microsoft 製品の無体財産権に関する法的な権利をお客さまに許諾するものではありま

せん。内部的な参照目的に限り、このドキュメントを複製して使用することができます。

© 2013 Microsoft. All rights reserved.

Page 3: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

3

目次

はじめに ................................................................................................................................................... 6

設計に関する考慮事項と目的 .................................................................................................................. 6

用語 ........................................................................................................................................................ 7

機能概要 ................................................................................................................................................ 8

インメモリ OLTP の特徴 ........................................................................................................................... 8

メモリ最適化テーブル ............................................................................................................................ 9

メモリ最適化テーブルのインデックス ......................................................................................................... 9

同時実行制御の改善 ........................................................................................................................ 10

ネイティブにコンパイルされたストアド プロシージャ ................................................................................... 10

インメモリ OLTP と DBCC PINTABLE の違い .................................................................................. 10

他社のソリューション ............................................................................................................................ 11

インメモリ OLTP の使用 ......................................................................................................................... 12

データベースの作成 ............................................................................................................................. 12

テーブルの作成 ................................................................................................................................... 13

行およびインデックスの格納 ..................................................................................................................... 15

行 ...................................................................................................................................................... 16

行ヘッダー ....................................................................................................................................... 16

ペイロード領域 ................................................................................................................................ 18

メモリ最適化テーブルのインデックス ....................................................................................................... 18

ハッシュ インデックス ......................................................................................................................... 18

範囲インデックス .............................................................................................................................. 21

データ操作 ......................................................................................................................................... 25

メモリ最適化テーブルで許可されている分離レベル ............................................................................ 26

削除 (DELETE) ........................................................................................................................... 28

更新 (UPDATE) と挿入 (INSERT) ............................................................................................ 28

読み取り ........................................................................................................................................ 30

Page 4: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

4

検証 .............................................................................................................................................. 30

T-SQL のサポート .......................................................................................................................... 31

メモリ内の行のガベージ コレクション .................................................................................................. 33

トランザクション分離および同時実行制御管理 ........................................................................................ 34

チェックポイントと回復 .............................................................................................................................. 37

トランザクション ログ ............................................................................................................................. 38

チェックポイント .................................................................................................................................... 41

チェックポイント ファイル .................................................................................................................... 42

チェックポイント処理 ......................................................................................................................... 43

チェックポイント ファイルのマージ ............................................................................................................ 43

自動マージ ..................................................................................................................................... 44

sys.sp_xtp_merge_checkpoint_files の手動マージ............................................................... 44

チェックポイント ファイルのガベージ コレクション ................................................................................... 45

回復 .................................................................................................................................................. 47

テーブルおよびストアド プロシージャのネイティブ コンパイル ......................................................................... 47

ネイティブ コンパイル ............................................................................................................................ 47

DLL の保守....................................................................................................................................... 48

テーブルのネイティブ コンパイル ............................................................................................................. 48

ストアド プロシージャのネイティブ コンパイル ........................................................................................... 49

コンパイルおよびクエリ処理 ............................................................................................................... 50

SQL Server 機能のサポート................................................................................................................. 51

管理エクスペリエンス ............................................................................................................................ 51

メタデータ ............................................................................................................................................... 52

カタログ ビュー ..................................................................................................................................... 52

動的管理オブジェクト .......................................................................................................................... 53

xEvents ........................................................................................................................................... 53

パフォーマンス カウンター ...................................................................................................................... 53

Page 5: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

5

メモリ使用量レポート ........................................................................................................................... 54

メモリ要件 .......................................................................................................................................... 54

リソース ガバナーによるメモリの管理 .................................................................................................. 55

AMR の使用 ......................................................................................................................................... 57

まとめ ..................................................................................................................................................... 57

詳細情報 .............................................................................................................................................. 58

Page 6: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

6

はじめに

最初の SQL Server が開発されたときには、メイン メモリが非常に高価であり、実際に処理する必要があると

き以外、データはディスク上に存在すべきであるという前提がありました。しかし、30 年以上を経てメモリの価格

が大幅に低下した今日、この前提は既に意味をなさなくなりました。同時に、廉価なマルチコア サーバーが市

場に見られるようになり、32 コアで 1 TB のメモリを搭載したサーバーを 50,000 ドル未満で購入することが

可能になりました。現在運用されている多くの OLTP データベースは 1 TB 以内のサイズなので、ディスクに

データを格納し、データをメモリに読み込んで処理する必要がある場合に I/O 負荷を生じさせる利点について

再検討する必要があります。また、OLTP データベースでは、データを更新し、ディスクに再書き込みする際にも

負荷が生じます。メモリ最適化テーブルは、ディスク ベースのテーブルとはまったく異なった方法で格納され、その

新しいデータ構造によってデータのアクセスと処理がさらに効率化されます。

メモリが入手しやすくなり、コアの数も増加している傾向を踏まえ、マイクロソフトの SQL Server 部門では、大

規模なメイン メモリやマルチコア CPU に対応して最適化されたデータベース エンジンの開発を開始しました。こ

のホワイト ペーパーでは、この新しいデータベース エンジン機能であるインメモリ OLTP の技術的な概要につい

て紹介します。

インメモリ OLTP の詳細については、「インメモリ OLTP (インメモリ最適化)」を参照してください。

設計に関する考慮事項と目的

真のメインメモリ データベースの運用に向けた動きは、3 つの基本的なニーズから生まれました。まず、ワークロー

ドで必要となるほとんどのデータ (またはすべてのデータ) をメインメモリに格納すること、次に、データ処理の待機

時間を短縮すること、最後に、特定の種類のワークロードを対象とする特別なデータベース エンジンをそのような

ワークロードに特化して調整することです。ムーアの法則が唱えたように、メモリの価格が大幅に下がり、メインメ

モリのサイズが拡大を続けた結果、最初のニーズおよび 2 番目のニーズ (一部) が満たされました (メモリのサ

イズが拡大すると読み取りの待機時間は短縮されますが、従来型のデータベース システムで必要とされるディス

クへの書き込みの待機時間は変わりません)。そして、インメモリ OLTP の登場により、データ変更処理の待機

時間が大幅に改善されます。特別なデータベース エンジンに対するニーズは、特定のクラスのワークロードを対

象に設計されたシステムは汎用システムの 10 倍以上優れたパフォーマンスを実現する可能性があるという考

えから生まれています。CEP (複合イベント処理)、データ ウェアハウス (DW)/ビジネス インテリジェンス (BI)、

そして OLTP などの最も特別なシステムでは、インメモリ構造に焦点を当てることにより、データ構造とアルゴリズ

ムが最適化されます。

マイクロソフトがインメモリ OLTP の開発を重視している主な理由は、メイン メモリのサイズの急速な拡大と価

格の低下です。さらに、64 ビット アーキテクチャおよびマルチコア プロセッサの実現がほぼ達成された今日、ほと

Page 7: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

7

んどの OLTP データベース、あるいはパフォーマンスが重要視されるデータセット全体を完全にインメモリ化する

可能性を考えることは決して非現実的ではありません。最大規模の金融、インターネット ショッピング、および航

空券予約システムのサイズは 500 GB ~ 5 TB 程度で、ワーキング セットも極めて小規模です。2012 年

の時点で、2 ソケットのサーバー 1 台でも、32GB の DIMMS (IBM x3680 X5 など) を使用して 2 TB

の DRAM を搭載することが可能です。さらに先を見越せば、今後数年のうちに 1 ~ 10 PB の容量を持つ

分散 DRAM ベースのシステムを 1 GB あたり 5 ドル未満で構築することも可能になると思われます。また、

不揮発性 RAM の利用が可能になるのも時間の問題です。

アプリケーションのデータのすべて (またはほとんど) を完全にメモリに常駐させることができるとしたら、SQL

Server のオプティマイザーが最初のバージョンから採用してきたコストの規則は、ほとんど完全に時代遅れとなり

ます。そのような規則では、アクセスの対象となるすべてのページは、ディスクからの物理的読み取りが必要であ

るという前提に基づいているからです。ディスクからの読み取りが不要であれば、SQL Server のオプティマイ

ザーでは別のコストのアルゴリズムを使用できます。さらに、ディスクの読み取りの待機時間が不要であれば、ロッ

クの解除の待機時間、ラッチの使用の待機時間、ログの書き込み終了の待機時間といった待機時間の数値

が必要以上に大きくなる可能性があります。インメモリ OLTP では、このような問題すべてを解決できます。イン

メモリ OLTP では新しいタイプのマルチバージョン オプティミスティック同時制御を採用しているため、ロックが解

除されるのを待たなければならないという問題が解消されます。また、生成されるログ データが大幅に減少し、

必要なログの書き込み量も減少するため、ログの書き込みの待機時間の遅延も少なくなります。

用語

SQL Server 2014 の "インメモリ OLTP" 機能とは、メモリ最適化テーブルで使用するテクノロジ群を意味し

ます。これまで SQL Server で提供されてきたメモリ最適化テーブルに対するものは、”ディスク ベース テーブル”

と呼ぶことにします。他には、次のような用語が使用されます。

"メモリ最適化テーブル" とは、インメモリ OLTP の一部として追加された新しいデータ構造を使用して

いるテーブルを意味します。詳細については、このホワイト ペーパーで説明します。

"ディスク ベース テーブル" とは、メモリ最適化テーブルのデータ構造を使用するテーブルです。これまで

SQL Server で使用されてきたデータ構造を使用し、ディスクに対する読み取り、書き込みの際の最

小単位として 8 KB のページが必要です。

"ネイティブ コードにコンパイルされたストアド プロシージャ" とは、インメモリ OLTP でサポートされるオブ

ジェクトのタイプで、マシン語コードにコンパイルされていて、メモリ最適化テーブルだけを使用した場合に

比べてパフォーマンスが向上する可能性があります。これに対して、"変換された Transact-SQL スト

アド プロシージャ" は、これまで SQL Server で使用されてきたものです。ネイティブ コードにコンパイ

ルされたストアド プロシージャは、メモリ最適化テーブルだけを参照します。

Page 8: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

8

"クロス コンテナ トランザクション" とは、メモリ最適化テーブルとディスク ベース テーブルの両方を参照

するトランザクションを意味します。

"互換性" とは、メモリ最適化テーブルを参照する変換された Transact-SQL を意味します。

機能概要

インメモリ OLTP を使用したほとんどのデータ処理操作では、ディスク ベース テーブルではなくメモリ最適化テー

ブルを操作していることがユーザーに意識されることはありません。しかし、データがメモリ最適化テーブルに格納さ

れている場合、SQL Server がデータを扱う方法は非常に異なります。このセクションでは、SQL Server でイ

ンメモリ OLTP の操作やデータを扱う方法がディスク ベースの場合と比較してどのように異なるかについて説明

します。また、他社のメモリ最適化データベースによるソリューションについても簡単に触れ、SQL Server のイン

メモリ OLTP との違いについても解説します。

インメモリ OLTP の特徴

インメモリ OLTP は SQL Server のリレーショナル エンジンに統合され、ユーザーはこれまでと同じインターフェ

イスを使用してアクセスすることができますが、内部の動作と機能は非常に異なります。図 1 はインメモリ

OLTP コンポーネントを使用した SQL Server エンジンの概要を示します。

図 1: インメモリ OLTP コンポーネントを含む SQL Server エンジン

Page 9: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

9

注目すべきは、メモリ最適化テーブルとディスク ベース テーブルのどちらを使用する場合でも、つまりネイティブに

コンパイルされたストアド プロシージャと変換された Transact-SQL のどちらを呼び出す場合でも、クライアント

アプリは同じ方法で TDS ハンドラーに接続するという点です。変換された Transact-SQL は相互運用性機

能を使用することでメモリ最適化テーブルにアクセスできますが、ネイティブにコンパイルされたストアド プロシー

ジャはメモリ最適化テーブルに直接アクセスできます。

メモリ最適化テーブル

メモリ最適化テーブルとディスク ベース テーブルの最も重要な違いは、メモリ最適化テーブルにアクセスする際に

はページをディスクからキャッシュに読み取る必要がないということです。その理由は、すべてのデータがメモリに常

駐しているからです。回復の際に使用する目的でのみチェックポイント ファイル (データとデルタ ファイルのペア)

がメモリ最適化ファイルグループに常駐するファイルに作成され、データの変更を把握するので、チェックポイント

ファイルは追加専用になります。

メモリ最適化テーブルの操作では、ディスク ベース テーブルの操作で使用するものと同じトランザクション ログを

使用し、このトランザクション ログはディスクに格納されます。システム クラッシュやサーバーのシャットダウンが起き

た場合には、メモリ最適化テーブルのデータ行はチェックポイント ファイルおよびトランザクション ログから再生成で

きます。

インメモリ OLTP には、SCHEMA_ONLY というオプションを使用して、非永続的でログが作成されないテーブ

ルを作成するオプションがあります。このオプションの名前が示すとおり、データには非永続的ですが、テーブルのス

キーマは永続的です。このようなテーブルはトランザクション処理の際に I/O 操作をまったく必要とせず、データ

は SQL Server の実行中にインメモリで使用できます。SQL Server のシャットダウンや AlwaysOn 可用

性グループのフェールオーバーが起きると、これらのテーブル内のデータは失われます。これらのテーブルは、関連

するデータベースが回復されると再作成されますが、その中にデータは含まれていません。このようなテーブルは、

ETL シナリオのステージング テーブルとして使用する場合や Web サーバーのセッション状態を格納する場合な

どに便利です。このときのデータに永続性はありませんが、これらのテーブルに対するすべての操作はその他のトラ

ンザクション要件を満たします。これらのテーブルはアトミックで、分離されていて、整合性があります。永続性の

ないテーブルを作成する構文については、「テーブルの作成」を参照してください。

メモリ最適化テーブルのインデックス

メモリ最適化テーブルのインデックスは、従来の B ツリーとして格納されません。メモリ最適化テーブルはハッシュ

インデックスをサポートしています。ハッシュ インデックスはハッシュ テーブルとして格納され、その中のリンクされたリ

ストは、ハッシュするすべての行を同じ値インデックスおよび範囲インデックスに接続します。メモリ最適化テーブル

Page 10: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

10

の場合、そのようなインデックスは、特別な Bw ツリーを使用して格納されています。メモリ最適化テーブルでの

非クラスター化インデックスは CTP2 以前では使用できませんでした。

どのメモリ最適化テーブルにも、必ずインデックスが 1 つあります。これは、すべての列を 1 つのテーブルに結合す

るためのインデックスです。メモリ最適化テーブルは、ディスク ベース テーブル ヒープのように、未整理の列の集ま

りとして格納されることはありません。

インデックスはディスクに格納されず、ディスク上のチェックポイント ファイルに反映されません。また、インデックス上

の操作はログに記録されません。インデックスは、メモリ最適化テーブル上のすべての変更操作の実行中に、ディ

スク ベース テーブル上での B ツリー インデックスのように自動的に管理されますが、SQL Server が再起動さ

れるとデータがメモリにストリーミングされるので、メモリ最適化テーブル上のインデックスは再構築されます。

同時実行制御の改善

メモリ最適化テーブルにアクセスする際、SQL Server はオプティミスティックなマルチバージョン同時実行制御を

実装します。これまで、SQL Server は、SQL Server 2005 で導入されたスナップショット ベースの分離レ

ベルによる同時実行制御をサポートしていると説明されていましたが、そのようなオプティミスティックな方法では

データ変更操作中にロックが取得されます。メモリ最適化テーブルではロックが取得されないので、ブロッキングが

原因となる待機が発生することはありません。

しかし、メモリ最適化テーブルを使用した場合でも待機が生じる可能性がまったくない訳ではないことに注意して

ください。待機には、トランザクション終了時のログの書き込み完了の待機などの種類もあります。それでも、メモ

リ最適化テーブルに変更を加える場合のログの書き込みは、ディスク ベース テーブルへのログの書き込みよりも

はるかに効率的なので待機時間はかなり短くなります。しかも、ディスクからデータを読み取るための待機も、

データ列へのロックのための待機も生じることはありません。

ネイティブにコンパイルされたストアド プロシージャ

実行のパフォーマンスは、ネイティブにコンパイルされたストアド プロシージャをメモリ最適化テーブルで使用する場

合に最適化されます。しかし、変換されたコードと比較すると、ネイティブにコンパイルされたストアド プロシージャ

内部で使用可能な Transact-SQL 言語のコンストラクトには制限があります。さらに、ネイティブにコンパイル

されたストアド プロシージャがアクセスできるのはメモリ最適化テーブルだけで、ディスク ベース テーブルにアクセス

することはできません。

インメモリ OLTP と DBCC PINTABLE の違い

DBCC PINTABLE は以前のバージョンの SQL Server で提供されていた機能で、データ ページがディスク

から読み取られると、メモリの "ピン留めされた" テーブルから削除されませんでした。データ ページは、最初に読

み取られる必要があったため、そのようなテーブルに初めてアクセスする際には、常にページ読み取りのコストが発

Page 11: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

11

生していました。このような "ピンで留められた" テーブルには、他のどのようなディスク ベース テーブルと比べても

違いはありません。同程度のロック、ラッチ、およびログが必要であることに加えて、ロックおよびログを必要とする

同じインデックス構造が使用されていました。インメモリ OLTP のメモリ最適化テーブルは、SQL Server のディ

スク ベース テーブルとはまったく異なります。使用するデータおよびインデックスの構造が異なり、ロックは使用され

ないので、これらのメモリ最適化テーブルへの変更のログ記録は、ディスク ベース テーブルへの変更のログ記録よ

りもはるかに効率的です。

他社のソリューション

OLTP データの処理には、2 種類の特別なエンジンが使用されます。最初のエンジンはメイン メモリ データベー

スです。Oracle には TimesTen、IBM には SolidDB という製品があり、その他にも主に埋め込みデータ

ベース領域を対象とした製品も数多く存在します。2 番目のエンジンはアプリケーション キャッシュまたはキー値

ストア (Velocity App Fabric Cache や Gigaspaces など) で、アプリや中間層メモリを強化してデータ

ベースの負荷を軽減します。これらのキャッシュは高機能化が進み、トランザクション、範囲インデックス、クエリと

いった機能が追加されています (たとえば、Gigaspaces には既にこれらの機能があります)。同時に、データ

ベース システムに高パフォーマンスのハッシュ インデックスのようなキャッシュ機能が追加され、複数のマシンで構

成されるクラスターにわたってスケールしています (VoltDB など)。インメモリ OLTP エンジンは、これらのエンジン

の利点を最大に生かすように設計されています。インメモリ OLTP には、キャッシュの持つパフォーマンスと、デー

タベースの持つ機能が備わっていると考えることができます。テーブルやインデックスをメモリ内に格納する機能が

あるので、データベース全体を完全なインメモリ システムとして作成することが可能です。さらに、高パフォーマンス

のインデックスとログ機能だけでなく、クエリ実行のパフォーマンスを大幅に改善するその他の機能も提供されてい

ます。

SQL Server のインメモリ OLTP には、他社製品には見られない次のような特徴があります。

メモリ最適化テーブルとディスク ベース テーブルの統合: メモリ常駐データベースへ段階的に移行するこ

とが可能になり、最もクリティカルなテーブルとストアド プロシージャのみがメモリ最適化オブジェクトとして

作成されます。

ネイティブにコンパイルされたストアド プロシージャ: 基本的なデータ操作処理の実行時間が大幅に短

縮されます。

メイン メモリにアクセスするために特に最適化されたハッシュ インデックスおよび BW ツリー インデックス

ページ上に格納されないデータ: ページ ラッチが不要です。

真のマルチバージョン オプティミスティック同時実行制御: どのような操作においてもロックやラッチは発生

しません

Page 12: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

12

SQL Server のインメモリ OLTP と他社製品の設計における最も顕著な違いは、”相互運用” の統合です。

標準的なハイエンド OLTP ワークロードでは、パフォーマンスのボトルネックは特定の領域に集中しています

(テーブルとストアド プロシージャの小さなセットなど)。データベース全体を強制的にメモリに常駐させることは高コ

ストであり非効率的です。しかし、これまで、主な他社製品ではこのようなアプローチが必要でした。SQL

Server では、高パフォーマンスで競合が多く発生する領域をインメモリ OLTP に移行でき、それらのメモリ最適

化テーブルに対する操作 (ストアド プロシージャ) をネイティブにコンパイルすることで最大のビジネス処理パ

フォーマンスを実現することができます。

インメモリ OLTP のもう 1 つの主な改善点は、メモリ最適化テーブル用のページ コンストラクトの削除です。こ

れにより、データ操作アルゴリズムがディスク最適化からメモリおよびキャッシュ最適化へと根本的に変化します。

既に示したように、インメモリ OLTP に関する混乱の 1 つは、テーブルがバッファー プール内でロックされるときに

“DBCC PINTABLE” である点です。しかしながら、多くの他社製品は、ページがメモリ内に常駐することを強

制される場合でさえ、依然としてページ コンストラクトを使用しています。たとえば、SAP HANA は依然としてイ

ンメモリの行ストアに 16KB ページを使用しており、高パフォーマンス環境では本質的にラッチ競合に悩まされま

す。

インメモリ OLTP の使用

インメモリ OLTP エンジンは、2013 年 6 月の CTP 以降、SQL Server 2014 の一部として利用できるよ

うになりました。インメモリ OLTP のインストールは、SQL Server のセットアップ アプリケーションに含まれていま

す。インメモリ OLTP コンポーネントは、64 ビット版の SQL Server 2014 にのみインストールでき、32 ビット

版ではサポートされていません。

データベースの作成

メモリ最適化テーブルを含むデータベースは、少なくとも 1 つの MEMORY_OPTIMIZED_DATA ファイル グ

ループを持つ必要があります。これらのファイル グループは、SQL Server がメモリ最適化テーブルを回復するた

めに必要なデータとデルタ ファイルのペアを格納するために使用し、ファイル グループを作成する構文は通常の

ファイル ストリーム ファイルグループを作成する際に必要な構文と同じですが、その構文内で CONTAINS

MEMORY_OPTIMIZED_DATA というオプションを指定する必要があります。メモリ最適化テーブルをサポー

トするデータベースの CREATE DATABASE ステートメントの例を以下に示します。

Page 13: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

13

CREATE DATABASE HKDB ON PRIMARY(NAME = [HKDB_data], FILENAME = 'Q:\data\HKDB_data.mdf', size=500MB), FILEGROUP [SampleDB_mod_fg] CONTAINS MEMORY_OPTIMIZED_DATA (NAME = [HKDB_mod_dir], FILENAME = 'R:\data\HKDB_mod_dir'), (NAME = [HKDB_mod_dir], FILENAME = 'S:\data\HKDB_mod_dir') LOG ON (name = [SampleDB_log], Filename='L:\log\HKDB_log.ldf', size=500MB) COLLATE Latin1_General_100_BIN2;

このコードの例では 3 つのドライブ (Q:、R:、および S:) にファイルが作成されます。このコードを実行する場合

は、実際にシステムで使用しているドライブに合わせてパス名を変更する必要があることに注意してください。この

例ではドライブ R: と S: 上のファイル名が同じなので、これらのすべてのファイルを同じドライブ上に作成する場

合には、これらのファイル名を区別できるように変更する必要があります。

また、バイナリ照合順序が指定されていることにも注意してください。現時点では、メモリ最適化テーブルのイン

デックスを使用できるのは、Windows (非 SQL) BIN2 照合順序だけで、ネイティブにコンパイルされたプロ

シージャがサポートするのは、これらの同じ照合順序での比較、ソート、およびグループ化のみです。指定の際に

は (例にある CREATE DATABASE ステートメントの時と同様に) データベース全体に対して既定のバイナリ

照合順序を使用するか、CREATE TABLE ステートメントの中のいずれかの文字データに対してこの照合順

序を指定します (比較、ソート、およびグループ化のクエリで照合順序を指定することも可能です)。

MEMORY_OPTIMIZED_DATA ファイル グループを既存のデータベースに追加して、そのファイル グループに

ファイルを追加することも可能です。次に例を示します。

ALTER DATABASE AdventureWorks2012

ADD FILEGROUP hk_mod CONTAINS MEMORY_OPTIMIZED_DATA;

GO

ALTER DATABASE AdventureWorks2012

ADD FILE (NAME='hk_mod', FILENAME='c:\data\hk_mod')

TO FILEGROUP hk_mod;

GO

テーブルの作成

メモリ最適化テーブルを作成する構文は、ディスク ベース テーブルを作成する構文とほぼ同じですが、いくつかの

制限に加えて必須の拡張があります。メモリ最適化テーブルであることは、MEMORY_OPTIMIZED = ON

句を使用して指定します。メモリ最適化テーブルには、以下に示すサポートされるデータ型の列だけを指定でき

ます。

ビット

すべての整数型: tinyint、smallint、int、bigint

Page 14: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

14

すべての金額型: money、smallmoney

すべての浮動型: float、real

日付/時刻型: datetime、smalldatetime、datetime2、date、time

numeric および decimal 型

すべての非 LOB 文字列型: char(n)、varchar(n)、nchar(n)、nvarchar(n)、

sysname

非 LOB バイナリ型: binary(n)、varbinary(n)

Uniqueidentifier

LOB データ型は指定できないことに注意してください。データ型が XML、CLR、および max の列は指定でき

ません。すべての行の長さは 8,060 バイトに制限され、行以外のデータは使用できません。実際には、8,060

バイトの制限はテーブル作成の時点で有効になるので、ディスク ベース テーブルとは異なり、2 つの

varchar(5,000) 列を含むメモリ最適化テーブルを作成することはできません。

メモリ最適化テーブルには、DURABILITY の値である SCHEMA_AND_DATA または SCHEMA_ONLY

のいずれかを定義できます (既定値は SCHEMA_AND_DATA です)。メモリ最適化テーブルで

DURABILITY = SCHEMA_ONLY と指定すると、テーブルのデータへの変更はログに記録されず、テーブル

内のデータはディスクに保持されません。このスキーマはデータベースのメタデータの一部として保持されるので、

SQL Server の再起動中にデータベースが回復されると空のテーブルが使用可能になります。

既に示したように、メモリ最適化テーブルには少なくとも 1 つのインデックスが必要ですが、この要件は、プライマリ

キーの制限をサポートするために自動的に作成されるインデックスによって満たされます。SCHEMA_ONLY オ

プションを使用して作成したテーブルを除くすべてのテーブルでは、宣言されたプライマリ キーが 1 つ必要です。

PRIMARY KEY の制限をサポートするには、少なくともインデックスを 1 つ宣言することが必要です。次の例で

は、PRIMARY KEY インデックスが HASH インデックスとして作成され、バケット カウントも指定する必要があ

ります。バケット カウントの値を選択する際のガイドラインのについては、ハッシュ インデックス格納の詳細について

説明する際に示します。

1 列だけのインデックスは、CREATE TABLE ステートメントでの列定義の中で作成できます (次の例を参照)。

BUCKET_COUNT 属性については、ハッシュ インデックスのセクションで説明します。

CREATE TABLE T1 ( [Name] varchar(32) not null PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 100000), [City] varchar(32) null, [State_Province] varchar(32) null, [LastModified] datetime not null, ) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);

Page 15: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

15

すべての列が定義された後で、複合インデックスを作成する方法もあります (次の例を参照)。次の例では、定

義に範囲インデックスを追加しています。注目すべきは、2 つの種類のインデックスの指定の違いです。一方は

キーワード HASH を使用していますが、他方は使用していません。どちらの種類のインデックスも

NONCLUSTERED として指定されていますが、ワード HASH が使用されていないインデックスは範囲インデッ

クスです。

CREATE TABLE T2 ( [Name] varchar(32) not null PRIMARY KEY NONCLUSTERED HASH WITH (BUCKET_COUNT = 100000), [City] varchar(32) null, [State_Province] varchar(32) null, [LastModified] datetime not null, INDEX T1_ndx_c2c3 NONCLUSTERED ([City],[State_Province]) ) WITH (MEMORY_OPTIMIZED = ON, DURABILITY = SCHEMA_AND_DATA);

メモリ最適化テーブルが作成されると、インメモリ OLTP エンジンは、このテーブルにアクセスするためだけの DML

ルーチンを生成してコンパイルし、このルーチンを DLL としてロードします。SQL Server そのものがメモリ最適

化テーブルでデータ操作 (レコードのクラック) を実行することはなく、メモリ最適化テーブルがアクセスされると、必

要な操作に対応する適切な DLL を呼び出します。

メモリ最適化テーブルの作成では、上記のデータ型の制限以外の制限はごくわずかしかありません。

DML トリガーなし

FOREIGN KEY および CHECK の制限なし

IDENTITY 列なし

PRIMARY KEY 以外の UNIQUE インデックスなし

インデックスの数は最大で 8 (PRIMARY KEY をサポートするインデックスも含む)

また、テーブルが作成された後、スキーマは変更できません。ALTER TABLE を使用する代わりに、テーブルを

削除して再作成する必要があります。さらに、特定のインデックス DDL コマンド (CREATE INDEX、ALTER

INDEX、DROP INDEX) はありません。インデックスは常にテーブル作成の一部として作成されます。

行およびインデックスの格納

インメモリ OLTP のメモリ最適化テーブルとインデックスは、ディスク ベース テーブルの場合とはまったく異なる方

法で格納されます。メモリ最適化テーブルは、ディスク ベース テーブルのようにページに格納されず、領域がエク

ステントから割り当てられることもありません、これは、ブロック アドレス可能なディスクではなくバイト アドレス可能

なメモリに合わせて最適化する設計方針によるものです。

Page 16: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

16

メモリ最適化テーブルは、ディスク ベース テーブルのようにページに格納されず、領域がエクステントから割り当て

られることもありません、これは、ブロック アドレス可能なディスクではなくバイト アドレス可能なメモリに合わせて

最適化する設計方針によるものです。行は、ヒープと呼ばれる構造から割り当てられ、SQL Server がディスク

ベース テーブルをサポートするタイプのヒープとは異なっています。あるテーブルの行は必ずしもそのテーブルの他の

行の近くに格納されておらず、テーブルのインデックスを使用して接続されているので、これを基にどの行が同じ

テーブルに属しているかが判断されます。そのため、メモリ最適化テーブルには、そこで作成されるインデックスが

少なくとも 1 つ必要であるという制限があります。テーブルの構造を提供するのがインデックスです。

行そのものの構造も、ディスク ベース テーブルに使用される行の構造とは非常に異なります。それぞれの行は

ヘッダー 1 つ、および行の属性を含むペイロード 1 つから構成されます。この構造およびヘッダー領域の内容の

拡張を図 2 に示します。

図 2 メモリ最適化テーブルの行の構造

行ヘッダー

行ヘッダーには、インメモリ OLTP のタイムスタンプが保持された 8 バイトのフィールドが 2 つ含まれています

(Begin-Ts および End-Ts)。メモリ最適化テーブルをサポートするすべてのデータベースは、これらのタイムスタ

ンプを生成するために使用される 2 つの内部カウンターを管理します。

行ヘッダー

ペイロード

Begin Ts End Ts StmtId IdxLinkCount

8 バイト 8 バイト 4 バイト 2 バイト

8 バイト x インデックス数

Page 17: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

17

Transaction-ID カウンターは、SQL Server インスタンスが再起動されるときにリセットされるグロー

バルな一意の値です。新しいトランザクションが開始されるたびにカウントが増加します。

Global Transaction Timestamp もグローバルで一意ですが、再起動時にリセットされません。こ

の値は、トランザクションが終了し、検証処理を開始するたびにカウントが増加します。新しい値は現在

のトランザクションのタイムスタンプとなります。Global Transaction Timestamp 値は、回復時に、

回復されたレコードの中で見つかった最新のトランザクション タイムスタンプを使って初期化されます。

(回復については、後で詳しく説明します。)

Begin Ts の値は、その行を挿入したトランザクションのタイムスタンプ、End Ts の値は、この行を削除したトラ

ンザクションのタイムスタンプです。ある特別な値 ("無限") が、削除されていない行の End Ts の値として使用

されます。ただし、行が最初に挿入されるとき、挿入トランザクションの完了前はトランザクションのタイムスタンプ

が不明なため、トランザクションがコミットされるまでグローバルな Transaction_ID 値が Begin-Ts に使用さ

れます。同様に、削除操作の場合も、トランザクション タイムスタンプが不明なため、削除された行の End-Ts

値はグローバルな Transaction_ID 値を使用し、実際の Transaction Timestamp が判明すると置き

換えられます。データ操作に関する説明でも触れますが、Begin Ts および End Ts の値は、他のどのトランザ

クションがこの行を参照できるかを決定します。

行ヘッダーには、ステートメントの ID の値も 4 バイト表示で含まれます。1 つのトランザクションのすべてのス

テートメントに一意の StmtId の値が含まれます。行が作成されると、その行を作成したステートメントの

StmtId が行に格納されます。同じ行が同じステートメントによって再度アクセスされた場合は、StmtId は無

視されます。

最後に、行ヘッダーには、この行を参照したインデックスの数を示す参照カウント数 (idxLinkCount) が 2 バ

イトの値で含まれます。idxLinkCount の値の次にはインデックス ポインターのセットが含まれます (詳細につい

ては次のセクションを参照してください)。ポインターの数は、インデックスの数と等しくなります。行がいずれのイン

デックスにも接続されなくなった場合でも、ガベージ コレクション (GC) メカニズムによって参照できるように、行の

始まりを示す参照値 1 が必要です。GC は、この最初の参照の "所有者" とみなされます。

既に説明したように、テーブル上のすべてのインデックスにポインターがあり、これらのポインターとインデックス デー

タ構造が行を結合します。インデックスのポインターで行を結合する以外に行をテーブルに結合する構造はない

ので、すべてのメモリ最適化テーブルには少なくとも 1 つのインデックスが必要であるという制限が生じます。また、

ポインターの数は行構造の一部であり、行が変更されることはないので、すべてのインデックスはメモリ最適化

テーブルの作成時に定義する必要があります。

Page 18: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

18

ペイロード領域

ペイロードは行そのもので、キー列およびその行の他の列を含みます (メモリ最適化テーブルのすべてのインデック

スは、実際にはインデックスをカバーします)。ペイロードの形式はテーブルによって異なります。テーブルの作成の

セクションで説明したように、インメモリ OLTP のコンパイラはテーブル操作のための DLL を生成します。行を

テーブルに挿入した際に使用したペイロードの形式がコンパイラに認識されていれば、すべての行操作のための

適切なコマンドも生成することもできます。

メモリ最適化テーブルのインデックス

すべてのメモリ最適化テーブルには、行を連結するインデックスが少なくとも 1 つ必要です。既に説明したように、

データ行はページには格納されないため、テーブルに対するすべてのページを取得するために参照できるページま

たはエクステントのコレクション、パーティションまたは割り当てユニットはありません。インデックスの種類のいずれか

に対するインデックス ページという概念はありますが、ディスク ベース テーブルのインデックスとは異なる方法で格

納されます。

インメモリ OLTP インデックスおよびデータ操作中にそれらに対して加えられる変更は、ディスクには一切書き込

まれません。データ行およびそのデータに対する変更のみがトランザクション ログに書き込まれます。メモリ最適化

テーブルのすべてのインデックスは、データベース回復中にインデックス定義に基づいて作成されます。詳細につい

ては、後の「チェックポイントと回復」を参照してください。

ハッシュ インデックス

ハッシュ インデックスはポインターの配列から構成され、配列のそれぞれの要素はハッシュ バケットと呼ばれます。

それぞれの行のインデックスのキー列にはそこに適用されるハッシュ関数が含まれ、その関数の結果によって、どの

ハッシュ バケットがその行で使用されるかが決まります。同じ値に対してハッシュを実行する (ハッシュ関数の実

行結果が同じである) キー値は、ハッシュ インデックスの同じポインターからアクセスされ、1 つのチェーンにリンクさ

れます。テーブルに行が追加されると、その行のインデックスのキー値にハッシュ関数が適用されます。キー値の重

複があると、常に同じ関数実行結果が生成され、同じチェーンに含まれます。

図 3 は、名前 の列にあるハッシュ インデックスの 1 つの行を示しています。この例では、インデックスのキー列に

ある文字列の長さに等しい値を返すシンプルなハッシュ関数を想定しています。最初の値 "Jane"は 4 にハッ

シュされます。これが、このハッシュ インデックスの最初のバケットになります (実際のハッシュ関数はもっとランダム

で予測不可能ですが、ここでは説明を簡潔にするために文字列の長さを使用しています)。Jane の行に対す

るハッシュ テーブルに 4 というエントリが示されます。この行は、他のどの行もポイントしていないため、レコード内

のインデックス ポインターは null です。

Page 19: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

19

図 3: 1 つの行があるハッシュ インデックス

図 4 では Greg という name 値を持つ行がテーブルに追加されたところを示しています。Greg も 4 にマッピ

ングされるとすると、Jane と同じバケットにハッシュされ、この行は Jane の行と同じチェーンにリンクされます。

図 4: 2 つの行があるハッシュ インデックス

テーブル定義の City 列に含まれている 2 番目のハッシュ インデックスは、2 番目のポインター フィールドを作

成します。テーブルのそれぞれの行には、それぞれの行をポイントする 2 つのポインターが作成され、それぞれの

テーブルで新たに 2 つの行をポイントできるようになりました。それぞれの行の最初のポインターは、Name イン

Page 20: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

20

デックスのチェーンの次の値をポイントし、2 番目のポインターは City インデックスのチェーンの次の値をポイントし

ます。図 5 は名前の同じハッシュ インデックスを表していますが、ここでは 3 つの行が 4 にハッシュされ、2 つの

行が 5 にハッシュされて、Name インデックスの 2 番目のバケットが使用されています。City 列の 2 番目のイ

ンデックスは 3 つのバケットを使用しています。6 のバケットはチェーンに 3 つの値があり、7 のバケットはチェーン

に 1 つの値があります。8 のバケットにも 1 つの値があります。

図 5: 同じテーブルにある 2 つのハッシュ インデックス

ハッシュ インデックスが作成されると、先の CREATE TABLE の例にもあるように、バケットの数を指定する必

要があります。指定するバケットの数は、インデックスのキー列の予想される基数 (一意の値の数) と同じかそれ

以上にして、なるべくそれぞれのバケットの行で 1 つの値がチェーンに含まれるようにすることをお勧めします。一

方で、それぞれのバケットがメモリを使用するので、大きすぎる値を選ばないよう注意する必要があります。指定

する値はそれより大きい次の 2 のべき乗に繰り上げられます。たとえば 50,000 という値は 65,536 になりま

す。バケットを余分に指定してもパフォーマンスの改善にならないばかりか、単にメモリを浪費することになり、行の

それぞれのバケットをチェックするスキャンのパフォーマンスが低下する可能性があります。

ハッシュ インデックスの構築を決定する場合は、実際に使用されるハッシュ関数はすべてのキー列に基づいてい

ることに留意してください。つまり、employees テーブルの lastname 列、firstname 列にハッシュ インデック

スがある場合、値 ”Harrison” および “Josh” を含む行は、値 “Harrison” および “John” を含む行とは

異なるバケットにハッシュされることになります。lastname 値のみを指定するクエリ、または厳密ではない

firstname 値 (“Jo%” など) を含むクエリは、そのインデックスをまったく使用することができません。

Page 21: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

21

範囲インデックス

特定の列に必要なバケットの数が不明な場合、または一定の幅の値を基にデータを検索する場合には、ハッ

シュ インデックスではなく範囲インデックスの作成を検討することをお勧めします。範囲インデックスは、2011 年

に Microsoft Research によって最初にビジョンが描かれ記述された Bw ツリーと呼ばれる新しいデータ構造

を使用して実装されます。Bw ツリーは、B ツリーのロックおよびラッチなしのバリエーションです。

Bw ツリーの一般的な構造は、インデックス ページが固定サイズではなく、構築された後は変更できない点を除

き、SQL Server の標準の B ツリーと同様です。標準の B ツリー ページと同様、各インデックス ページには順

序付けされたキー値が含まれ、各値には対応するポインターが存在します。インデックスの上位のレベルでは、内

部ページと呼ばれるものにおいて、ポインターはツリーの次のレベルにあるインデックス ページをポイントし、リーフ

レベルでは、ポインターはデータ行をポイントします。インメモリ OLTP のハッシュ インデックスの場合と同様、複

数のデータ行をリンクできます。範囲インデックスの場合は、インデックス キーに対して同じ値を持つ行がリンクさ

れます。

Bw ツリーと SQL Server の B ツリーの 1 つの大きな違いは、ページ ポインターが物理ページ番号ではなく

論理ページ ID (PID) である点です。PID は、マッピング テーブル内の位置を示します。マッピング テーブルは、

各 PID を物理メモリ アドレスと接続します。インデックス ページが更新されることはありません。代わりに、新し

いページによって置き換えられ、マッピング テーブルは同じ PID が新しい物理メモリ アドレスを示すように更新さ

れます。

図 6 は、Bw ツリーの一般的な構造とページ マッピング テーブルを示しています。

図 6: Bw ツリーの一般的な構造

ページ マッピング テーブル

ルート

非リーフ ページ

リーフ ページ

データ行

キー キー

Page 22: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

22

すべての PID 値が図 6 に示されている訳ではありません。また、マッピング テーブルは、使用中のすべての

PID 値を示している訳ではありません。インデックス ページは、インデックスが参照するキー値を示しています。内

部インデックス ページ内の各インデックス行には、キー値 (示されています) および次の下位レベルにあるページ

の PID が含まれます。キー値は、参照されるページ上の最高値です (これは標準の B ツリー インデックスとは

異なることに注意してください。標準の B ツリー インデックスでは、インデックス行は次の下位レベルにあるページ

上の最小値を格納します)。

リーフ レベルのインデックス ページにもキー値が含まれますが、PID ではなく、データ行の実際のメモリ アドレスが

含まれます。このデータ行は、すべてが同じキー値を持つデータ行のチェーン内の先頭である可能性があります。

Bw ツリーと SQL Server の B ツリーのもう 1 つの大きな違いは、リーフ レベルで、データ変更がデルタ値の

セットを使用して追跡される点です。リーフ ページそのものは変更ごとに置き換えられません。ページに対する各

更新 (そのページ上のキー値の挿入または削除である可能性があります) は、加えられた変更を示すデルタ レ

コードを含むページを生成します。更新は、2 つの新しいデルタ レコードによって表されます。1 つは元の値を削

除するためのもので、もう 1 つは新しい値を挿入するためのものです。各デルタ レコードが追加されると、マッピ

ング テーブルは、新しく追加されたデルタ レコードを含むページの物理アドレスで更新されます。図 7 はこの動

作を示しています。マッピング テーブルは、論理アドレス P を含む単一のページのみを示しています。マッピング

テーブル内の物理アドレスは、最初は、ページ P として示されている対応するリーフ レベル インデックス ページの

メモリ アドレスでした。インデックス キー値 50 を含む新しい行 (テーブルのデータ内でまだ発生していないとしま

す) がテーブルに追加されると、インメモリ OLTP はデルタ レコードをページ P に追加して新しいキーの挿入を

示し、ページ P の物理アドレスは最初のデルタ レコード ページのアドレスを示すように更新されます。次に、イン

デックス キー値 48 を含む行のみがテーブルから削除されると、インメモリ OLTP はキー 48 を含むインデックス

行を削除する必要があるので、別のデルタ レコードが作成されページ P の物理アドレスが再び更新されます。

物理アドレス

マッピング テーブル

Δ: レコード 48 の削除

Δ: レコード 50 の挿入

DELETE 後の物理アドレス

INSERT 後の物理アドレス

元の物理アドレス ページ P

Page 23: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

23

図 7: リーフ レベル インデックス ページにリンクされているデルタ レコード

インデックス ページの構造

インメモリ OLTP の範囲インデックス ページは、ディスク ベース テーブル上のインデックスとは異なり、固定サイズ

ではありません。ただし、最大インデックス ページ サイズは 8 KB のままです。

メモリ最適化テーブルの範囲インデックス ページにはすべて、次の情報を含むヘッダー領域があります。

PID: マッピング テーブルへのポインター

Page Type: リーフ、内部、デルタ、または特殊

Right PID: 現在のページの右にあるページの PID

Height: 現在のページからリーフまでの垂直方向の距離

Page statistics: デルタ レコードの数およびページ上のレコードの数

Max Key: ページ上の値の上限

さらに、リーフ ページと内部ページには、2 または 3 つの固定長配列が含まれます。

Values: これは実際にはポインター配列です。配列内の各エントリは 8 バイト長です。内部ページの

場合、エントリには次のレベルにあるページの PID が含まれ、リーフ ページの場合、エントリには等しい

キー値を持つ行のチェーン内の先頭の行のメモリ アドレスが含まれます。(技術的には PID を 4 バイ

トで格納することができますが、同じ値構造をすべてのインデックス ページで使用できるようにするために

は、配列ではエントリあたり 8 バイトが可能です。)

Offsets: この配列は可変長キーを持つインデックスのページの場合のみ存在します。各エントリは 2

バイトで、ページ上のキー配列内で対応するキーが開始する位置を示すオフセットが含まれます。

Keys: これはキー値の配列です。現在のページが内部ページの場合、キーは PID によって参照される

ページの最初の値を表します。現在のページがリーフ ページの場合は、キーは行のチェーン内の値です。

最小のページは、通常はデルタ ページです。内部またはリーフ ページ内と同じ情報の大半を含むヘッダーがあり

ます。ただし、デルタ ページ ヘッダーには、リーフまたは内部ページについて説明した配列はありません。デルタ

ページには、操作コード (挿入または削除) と値が含まれます。値は、レコードのチェーン内の先頭行のメモリ ア

ドレスです。最後に、デルタ ページには、現在のデルタ操作のキー値も含まれます。実際、デルタ ページは単一

の要素を保持するミニインデックス ページと考えることができます。一方、標準のインデックス ページは N 要素の

配列を格納します。

Bw ツリーの内部の再編成操作

Bw ツリーの構造を管理するために要求することができる操作には、統合、分割、およびマージの 3 つがありま

す。これらのすべての操作では、既存のインデックス ページは変更されません。PID 値に対応する物理アドレス

Page 24: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

24

を更新するためにマッピング テーブルに変更が加えられることがあります。インデックス ページで新しい行を追加す

る (または行を削除する) 必要がある場合は、新しいページが作成され、PID 値がマッピング テーブルで更新さ

れます。

デルタ レコードの統合

SQL Server がインデックスを通じて検索しているときにインデックス ページのコンテンツと共にデルタ レコードの

変更を考慮する必要がある場合、デルタ レコードの長いチェーンによって検索パフォーマンスが低下する可能性

があります。インメモリ OLTP が新しいデルタ レコードを既に 16 要素を含むチェーンに追加しようとすると、デル

タ レコード内の変更は参照されるインデックス ページに統合され、ページが再構築されて、統合をトリガーした

新しいデルタ レコードによって示される変更が含められます。新しく再構築されたページは同じ PID を持ちます

が、メモリ アドレスは新しくなります。古いページ (インデックス ページとデルタ ページ) はガベージ コレクション対

象としてマークされます。

完全なインデックス ページの分割

BW ツリー内のインデックス ページは、単一行の格納から始まり最大 8K バイトの格納まで、必要に応じて拡

張します。インデックス ページが 8K バイトに拡張すると、単一行の新しい挿入により、インデックス ページは分

割します。内部ページの場合、これは、別のキー値およびポインターを追加するための余地がなくなったことを意

味します。リーフ ページの場合は、すべてのデルタ レコードが組み込まれると行が大きすぎてページに適合しなく

なることを意味します。リーフ ページのページ ヘッダー内の統計情報は、デルタ レコードを統合するために必要

な領域の容量を追跡します。その情報は、新しいデルタ レコードが追加されるたびに調整されます。分割操作

は、ここで説明するように、2 つのアトミックなステップによって行われます。Ps は P1 と P2 に分割されるページ、

Pp は親ページであり、Ps をポイントする行を含むとします。

ステップ 1: 2 つの新しいページ P1 および P2 を割り当て、新しく挿入された行を含め、ページ Ps の行を

これらのページに分割します。ページ マッピング テーブル内の新しいスロットは、ページ P2 の物理アドレスを

格納するために使用されます。これらのページ P1 および P2 は、同時操作からはまだアクセスできません。

さらに、P1 から P2 への “論理” ポインターが設定されます。これが完了したら、1 つのアトミックな操作で、

ページ マッピング テーブルを更新し、Ps の代わりに P1 をポイントするようにポインターを変更します。この操

作の後、ページ Ps へのポインターはなくなります。

ステップ 2: ステップ 1 の後、親ページ Pp は P1 をポイントしますが、親ページからページ P2 への直接ポ

インターはありません。ページ P2 はページ P1 経由でのみ到達可能です。親ページからページ P2 へのポイ

ンターを作成するには、新しい親ページ Pnp を割り当て、ページ Pp のすべての行をコピーし、ページ P2 を

ポイントするための新しい行を追加します。これが完了したら、1 つのアトミックな操作でページ マッピング

テーブルを更新して、Pp から Pnp へのポインターを変更します。

Page 25: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

25

隣接するインデックス ページのマージ

削除操作によって最大ページ サイズ (現時点では 8K) の 10% 未満、または行が 1 つだけのインデックス

ページ P が残された場合、ページ P は隣接するページとマージされます。分割と同様、これは複数のステップに

よる操作です。この例では、ページを左側の隣接するページ (より小さい値を含むページ) とマージします。行が

ページ P から削除されると、削除用のデルタ レコードが通常どおり追加されます。さらに、ページ P がマージの

条件を満たしているかどうか (削除後の残りの容量が最大ページ サイズの 10% 未満になるかどうか) を判断

するためのチェックが行われます。条件が満たされる場合、マージは以下で説明するように 3 つのアトミックなス

テップで実行されます。この例では、Pp が親ページで、ページ P をポイントする行を含むとします。ページ Pln は

左側の隣接するページを表します。その最大キー値は 5 であるとします。つまり、ページ Pln をポイントする親

ページ Pp 内の行には値 5 が含まれます。ページ P 上のキー値 10 を含む行を削除します。削除後、ページ

P には 1 行のみが残され、そのキー値は 9 です。

ステップ 1: キー値 10 を表すデルタ ページ DP10 が作成され、そのポインターは P をポイントするように設

定されます。さらに、特別な “マージ-デルタ ページ” DPm が作成され、DP10 をポイントするようにリンクさ

れます。この段階では、ページ DP10 および DPm は同時トランザクションからは見えません。1 つのアトミック

なステップで、ページ マッピング テーブル内のページ P へのポインターが DPm をポイントするように更新され

ます。このステップの後、親ページ内のキー値 10 のエントリは DPm をポイントするようになります。

ステップ 2: このステップでは、ページ Pp 内のキー値 5 を表す行が削除され、キー値 10 のエントリがペー

ジ Pln をポイントするように更新されます。これを行うために、新しい非リーフ ページ Pp2 が割り当てられ、

キー値 5 を表す行を除き、Pp からのすべての行がコピーされます。次に、キー値 10 の行がページ Pln を

ポイントするように更新されます。これが完了したら、1 つのアトミックなステップでページ Pp をポイントする

ページ マッピング テーブル エントリがページ Pp2 をポイントするように更新されます。ページ Pp は到達不能

になります。

ステップ 3: このステップでは、リーフ ページ P および Pln がマージされ、デルタ ページが削除されます。これ

を行うために、新しいページ Pnew が割り当てられ、P および Pln の行がマージされます。デルタ ページの変

更は新しい Pnew に含まれます。次に、1 つのアトミックな操作でページ Pln をポイントするページ マッピング

テーブル エントリがページ Pnew をポイントするように更新されます。

データ操作

SQL Server のインメモリ OLTP では、タイムスタンプの役割を果たす内部のトランザクション ID (この説明で

はタイムスタンプと呼びます) を管理することによって、どの列のバージョンがどのトランザクションに表示されるかが

決定されます。タイムスタンプは、トランザクションがコミットされると増加するカウンターによって生成されます。ある

トランザクションの開始時刻が、そのトランザクションの開始時点で最も値の大きいそのデータベースのタイムスタ

Page 26: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

26

ンプになります。トランザクションがコミットされると新しいタイムスタンプが生成され、それがトランザクションを一意

に識別するタイムスタンプになります。タイムスタンプは、次のような内容を指定するために使用します。

コミット/終了時刻: 特定の時刻のデータのコミットを変更するトランザクションはトランザクションの「コ

ミット」または「終了時刻」のタイムスタンプと呼ばれます。コミット時刻により、シリアル化履歴の中でトラ

ンザクションの位置が効果的に識別されます。

レコードの 1 つのバージョンの有効期間: 図 2 で見たように、データベースすべてのレコードには、開

始タイムスタンプ (Begin Ts) と終了タイムスタンプ (End Ts) という 2 つのタイムスタンプが含まれ

ています。開始タイムスタンプは、そのバージョンを作成したトランザクションのコミット時刻を表し、終了

タイムスタンプは、そのバージョンを削除した (そして新しいバージョンに置換した) トランザクションのコ

ミット タイムスタンプを表します。レコード バージョンの有効期間は、そのバージョンが他のトランザクショ

ンに表示されている範囲のタイムスタンプを表します。図 5 の例では、Susan のレコードが 90 のとき

に Vienna から Bogota に更新されています。

論理的な読み取り時刻: 読み取り時刻は、トランザクションの開始時刻から現在時刻までの間での

任意の値です。読み取りの際には、有効期間が論理的な読み取り時刻に重複するバージョンだけが

表示されます。読み取りコミット以外のすべての分離レベルについては、トランザクションの論理的な読

み取り時刻がトランザクションの開始時刻に対応しています。読み取りコミットについては、トランザク

ション内のステートメントの開始に対応しています。

バージョンの表示可能性の概念は、メモリ OLTP の正しい同時実行制御の基本です。論理的な読み取り時

刻の RT を使用して実行しているトランザクションには、開始タイムスタンプの値が RT より小さく、終了タイムス

タンプの値が RT より大きいバージョンだけが表示されなければなりません。

メモリ最適化テーブルで許可されている分離レベル

メモリ最適化テーブルでのデータ操作は、常にオプティミスティックなマルチバージョン同時実行制御 (MVCC) を

使用します。オプティミスティックなデータ アクセスは、トランザクション分離を提供するためにロックまたはラッチを

使用しません。後半のセクションでは、このロックおよびラッチなしの動作がどのように管理されるか、および許可さ

れているトランザクション分離レベルの理由について説明します。このセクションでは、データ アクセスおよび変更

操作の基本を理解するために必要なトランザクション分離レベルの詳細についてのみ説明します。

メモリ最適化テーブルにアクセスするトランザクションでは、次の分離レベルがサポートされています。

SNAPSHOT REPEATABLE READ SERIALIZABLE

トランザクション分離レベルは、ネイティブにコンパイルされたストアド プロシージャの ATOMIC ブロックの一部とし

て指定できます。別の方法として、変換された Transact-SQL からメモリ最適化テーブルにアクセスする際に、

Page 27: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

27

テーブル レベルのヒントまたは MEMORY_OPTIMIZED_ELEVATE_TO_SNAPSHOT という新しいデータベース オ

プションを使用して分離レベルを指定することもできます。このオプションについては、メモリ最適化テーブルにアク

セスするための分離レベルを確認した後で説明します。

トランザクション分離レベルの指定は、ネイティブにコンパイルされたストアド プロシージャでは必須です。テーブル

ヒントでの分離レベルの指定は、変換された Transact-SQL のユーザー トランザクションからメモリ最適化テー

ブルにアクセスする際に必須です。

分離レベル READ COMMITTED は、メモリ最適化テーブルに対してオートコミット (単一ステートメント) トラ

ンザクションでサポートされています。明示的および暗示的なユーザー トランザクションではサポートされていませ

ん (暗示的なトランザクションとは、セッション オプション IMPLICIT_TRANSACTIONS の下で呼び出される

トランザクションです。このモードでは、動作は明示的なトランザクションと同じですが、BEGIN

TRANSACTION ステートメントは必要ありません。任意の DML ステートメントがトランザクションを開始しま

す。トランザクションは明示的にコミットまたはロールバックされる必要があります。BEGIN TRANSACTION の

みが暗示的です)。分離レベル READ_COMMITTED_SNAPSHOT はメモリ最適化テーブルに対してオー

トコミット トランザクションで、クエリがディスク ベース テーブルにアクセスしない場合にのみサポートされます。また、

変換された Transact-SQL を SNAPSHOT 分離と共に使用して開始されたトランザクションは、メモリ最適

化テーブルにアクセスできません。変換された Transact-SQL を REPEATABLE READ または

SERIALIZABLE 分離と共に使用して開始されたトランザクションは、SNAPSHOT 分離を使用してメモリ最

適化テーブルにアクセスする必要があります。

ここでは、前に示した行のインメモリ構造を使って DML 操作がどのように実行されるかを説明します。行は内容

を順に列挙し、山かっこで囲んで表します。トランザクション ID が 100 の TX1 というトランザクションが

SERIALIZABLE 分離レベルで実行されているとします。開始タイムスタンプは 240 で、次の 2 つの操作が

実行されます。

DELETE the row <Greg , Lisbon>

UPDATE <Jane, Helsinki> to <Jane, Perth>

同時に、他に 2 つのトランザクションがこの行を読み取ります。TX2 はオートコミットで、タイムスタンプ 243 で

実行される単一のステートメント SELECT です。TX3 は明示的なトランザクションで、ある行を読み取り、次

に SELECT ステートメントで読み取った値に基づいて別の行を更新します。タイムスタンプは 246 です。

まず、データ更新トランザクションを確認します。このトランザクションはデータベースのシリアル化順序に対応して

開始したことを表す開始タイムスタンプを取得することによって開始されます。この例では、タイムスタンプは 240

です。

Page 28: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

28

操作中、トランザクション TX1 は、開始タイムスタンプが 240 以下で、終了タイムスタンプが 240 より大きい

レコードだけにアクセスできます。

削除 (DELETE)

トランザクション TX1 は、まずインデックスの 1 つから <Greg, Lisbon> を検出します。この行を削除するた

めに、行のタイムスタンプは 100 に設定され、値がトランザクション ID であることを示す追加フラグ ビットが含ま

れます。この行にアクセスしようとする他のトランザクションは、終了タイムスタンプにその行が削除された可能性が

あることを示すトランザクション ID (100) が含まれていることを見つけます。次に、トランザクション マップで

TX1 を探し、トランザクション TX1 がまだアクティブであるかどうかを調べて、<Greg, Lisbon> の削除が完

了しているかどうかを判断する必要があります。

更新 (UPDATE) と挿入 (INSERT)

次に、この操作を元の行全体を削除 (DELETE) する操作と完全に新しい行を挿入 (INSERT) する操作

の 2 つの操作に分割することによって、<Jane, Helsinki> の更新が実行されます。この操作は、トランザク

ション ID であることを示すフラグ ビットを含む開始タイムスタンプ 100 で、新しい行 <Jane, Perth> を構築

し、次に終了タイムスタンプを ∞ (無限) に設定することによって開始されます。この行にアクセスしようとするトラ

ンザクションは、トランザクション TX1 がまだアクティブであるかどうかを判断し、<Jane, Perth> を表示できる

かどうかを判断する必要があります。さらに、<Jane, Perth> が、両方のインデックスにリンクすることで、挿入

されます。次に、<Jane, Helsinki> が、「削除 (DELETE)」のセクションで説明したように削除されます。

<Jane, Helsinki> を更新または削除しようとする他の操作は、終了タイムスタンプに無限ではなくトランザク

ション ID が含まれていることを検出し、書き込み/書き込みの競合が発生していると結論付け、直ちに中止し

ます。

この時点で、トランザクション TX1 は操作を完了していますが、まだコミットしていません。コミット処理は、このト

ランザクションの終了タイムスタンプを取得することによって開始されます。この例では、この終了タイムスタンプは

250 で、このトランザクションの更新が論理的にすべて発生するデータベースのシリアル化順序の時点を表しま

す。この終了タイムスタンプを取得する際、トランザクションは、チェックを実行して現在の分離レベルの違反がな

いか確認する検証と呼ばれる状態に入ります。検証が失敗すると、トランザクションは中止されます (検証につ

いては、この後のセクションで簡単に説明します)。また、SQL Server は、この検証フェーズの終了時にトラン

ザクション ログを書き込みます。

トランザクションは、基本的にはそれぞれの操作に関連付けられたバージョンへのポインターに対する削除/挿入

操作のリストである書き込みセットへのすべての変更を追跡します。このトランザクションの書き込みセット、および

変更される行は、図 8 で緑色の枠で示されています。この書き込みセットは、このトランザクションのログの内容

を構成しています。トランザクションでは通常、ID およびコミット タイムスタンプが含まれている単一のログ レコー

Page 29: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

29

ドだけが生成されますが、トランザクションで削除または挿入されたすべてのレコードのバージョンを生成することも

あります。ディスク ベース テーブルにあるような、影響を受けるそれぞれの行の個別のログ レコードはありません。

ただし、ログ レコードのサイズには上限があるため、メモリ最適化テーブルでのトランザクションがこの上限を上回

る場合には、複数のログ レコードが生成されることもあります。ログ レコードが記憶域に書き込まれると、トランザ

クションの状態はコミット済みに変わり、後処理が開始されます。

後処理では、書き込みセットの反復処理と、それぞれのエントリの処理が次のように実行されます。

DELETE 操作では、行の終了タイムスタンプがトランザクションの終了タイムスタンプ (この例では 250) に

設定され、行の終了タイムスタンプ フィールドの種類フラグがクリアされる。

INSERT 操作では、影響を受ける行の開始タイムスタンプがトランザクション終了タイムスタンプ (この例で

は 250) に設定され、行の開始タイムスタンプ フィールドの種類フラグがクリアされる。

行の以前のバージョンのリンクの解除と削除は、実際には、ガベージ コレクション システムによって処理されます。

詳細については、後で説明します。

図 8: トランザクションによるテーブルの変更

Page 30: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

30

読み取り

次に、読み取りトランザクション TX2 および TX3 を確認します。これらは TX1 と同時に処理されます。TX1

は行 <Greg , Lisbon> を削除し、<Jane, Helsinki> を <Jane, Perth> に更新していることに注意

してください。

TX2 は、次のように、テーブル全体を読み取るオートコミット トランザクションです。

SELECT Name, City

FROM T1

TX2 のセッションは既定の分離レベル READ COMMITTED で実行されますが、ここで示されているように、

ヒントが指定されず、T1 はメモリ最適化テーブルであるため、データは SNAPSHOT 分離を使用してアクセス

されます。TX2 はタイムスタンプ 243 で実行されるため、その時点で存在する行を読み取ることができます。し

かし、タイムスタンプ 243 の時点で有効ではなくなっている <Greg, Beijing> にアクセスすることはできませ

ん。<Greg, Lisbon> の行はタイムスタンプ 250 の時点で削除されますが、タイムスタンプ 200 から 250

までが有効なので、トランザクション TX2 はこれを読み取ることができます。TX2 は、<Susan, Bogota> お

よび <Jane, Helsinki> の行も読み取ることができます。

TX3 はタイムスタンプ 246 で開始される明示的トランザクションです。1 つの行を読み取り、読み取った値に

基づいて、別の行を更新します。

DECLARE @City nvarchar(32);

BEGIN TRAN TX3

SELECT @City = City

FROM T1 WITH (REPEATABLEREAD)

WHERE Name = 'Jane';

UPDATE T1 WITH (REPEATABLEREAD)

SET City = @City

WHERE Name = 'Susan';

COMMIT TRAN -- commits at timestamp 255

TX3 では、SELECT が、タイムスタンプ 243 の時点でまだアクセス可能である行 <Jane, Helsinki> を読

み取ります。 次に、<Susan, Bogota> の行が <Susan, Helsinki> に更新されます。しかし、トランザク

ション TX3 が、TX1 がコミットした後にコミットしようとすると、SQL Server は <Jane, Helsinki> が別のト

ランザクションによって更新されたことを検出します。これは要求された REPEATABLE READ 分離の違反で

あるため、TX3 のコミットは失敗し、TX3 はロール バックします。この検証については、次のセクションで詳しく説

明します。

検証

Page 31: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

31

メモリ最適化テーブルに関連するトランザクションの最後のコミットの前に、SQL Server は検証ステップを実行

します。データ修正の途中でロックが取得されないので、要求された分離レベルに基づいて、変更されたデータは

無効なデータになる可能性があります。コミット処理のこのフェーズでは、無効なデータがないことが確認されます。

次のリストは、分離レベルによって生じる可能性のある違反の例です。発生しやすい違反やコミット依存については、

分離レベルおよび同時実行制御についてより詳細に説明するその他のホワイト ペーパーを参照してください。

メモリ最適化テーブルが SNAPSHOT 分離でアクセスされると、COMMIT が試行された際に次のような違反

エラーが発生する可能性があります。

現在のトランザクションが、現在のトランザクションより前にコミットされた別のトランザクションによって挿入

された行と同じ主キー値を持つ行を挿入すると、エラー 41325 (SERIALIZABLE の検証に失敗したため、

現在のトランザクションのコミットに失敗しました) が発生し、トランザクションは中止されます。

メモリ最適化テーブルが REPEATABLE READ 分離でアクセスされると、COMMIT が試行された際に、次の

ような違反エラーも発生する可能性があります。

現在のトランザクションが、現在のトランザクションより前にコミットされた別のトランザク

ションによって更新された行を読み取ると、エラー 41305 (REPEATABLE READ の検

証に失敗したため、現在のトランザクションのコミットに失敗しました) が発生し、トランザクションは

中止されます。

メモリ最適化テーブルが SERIALIZABLE 分離でアクセスされると、COMMIT が試行された際に、次のような

違反エラーも発生する可能性があります。

現在のトランザクションが、指定したフィルター条件を満たす有効な行の読み取りに失敗するか、または

他のトランザクションによって挿入され、指定したフィルター条件を満たすファントム行に遭遇すると、コ

ミットは失敗します。このトランザクションは、同時トランザクションがないかのように実行される必要があり

ます。すべてのアクションは、論理的には単一のシリアル化ポイントで発生します。これらの条件のいずれ

かが満たされない場合、エラー 41325 が発生し、トランザクションは中止されます。

T-SQL のサポート

メモリ最適化テーブルは、変換された Transact-SQL を使用した相互運用によって、またはネイティブにコンパ

イルされたストアド プロシージャによってアクセスできます。

Page 32: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

32

変換された Transact-SQL

相互運用機能を使用すると、メモリ最適化テーブルを使用するときに Transact-SQL のセキュリティ全般に実

質的にアクセスできるようになりますが、ネイティブにコンパイルされたストアド プロシージャを使用してメモリ最適

化テーブルにアクセスする場合と同じパフォーマンスは期待できません。相互運用は、アドホック クエリを実行する

際の手段、またはアプリケーションをインメモリ OLTP に移行する際にほとんどのパフォーマンス クリティカルなプロ

シージャを移行する前の移行処理の 1 ステップとして使用する手段として適しています。メモリ最適化テーブル

とディスク ベース テーブルの両方にアクセスする必要がある場合にも、変換された Transact-SQL を使用す

る必要があります。

相互運用を使用するメモリ最適化テーブルにアクセスする際にサポートされていない Transact-SQL の機能

を以下に示します。

TRUNCATE TABLE

MERGE (メモリ最適化テーブルがターゲットの場合)

動的カーソルおよびキーセット カーソル (自動的に機能低下され静的カーソルになる)

複数データベース間のクエリ

複数データベース間のトランザクション

リンクされたサービス

ロック ヒント: TABLOCK、XLOCK、PAGLOCK など。(NOLOCK はサポートされますが、メッセージ

を表示することなく無視されます。)

分離レベル ヒント: READUNCOMMITTED、 READCOMMITTED、および

READCOMMITTEDLOCK

メモリ最適化テーブルのテーブル型およびテーブル変数がサポートされていないのは CTP1 だけです

ネイティブにコンパイルされたプロシージャでの T-SQL

ネイティブにコンパイルされたストアド プロシージャを使用すると、メモリ最適化テーブルのデータにアクセスして

Transact-SQL を最も高速に実行できます。しかし、これらのプロシージャで使用できる Transact-SQL に

は、多くの制限があります。ネイティブにコンパイルされたプロシージャでアクセスし、処理できるデータ型や照合順

序にも制限があります。サポートされている Transact-SQL ステートメントおよび使用可能なデータ型や演算

子の一覧については、該当するドキュメントを参照してください。なお、ネイティブにコンパイルされた ストアド プロ

シージャ内には、ディスク ベース テーブルからはアクセスできません。

このような制限があるのは、内部的に、それぞれのテーブルのそれぞれの操作に対して、個別の関数が作成され

る必要があるためです。そのためのインターフェイスは、今後のバージョンで拡張される予定です。

Page 33: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

33

メモリ内の行のガベージ コレクション

インメモリ OLTP はマルチバージョン システムなので、DELETE 操作と UPDATE 操作 (および中止された

INSERT 操作) により、最終的に古くなる行バージョンが生成されます。つまり、これらの行バージョンは、どのト

ランザクションからも見えなくなります。これらの不要なバージョンは、インデックス構造のスキャンを低下させ、再要

求する必要がある未使用メモリを作成します。

メモリ最適化テーブル内の古いバージョンに対するガベージ コレクション処理は、SQL Server がスナップショット

ベースの分離レベルのいずれかを使用してディスク ベース テーブルに対して実行するバージョン ストア クリーン

アップと似ています。ただし、クリーンアップが tempdb ではなく、インメモリ テーブル構造そのもので行われる点

が大きく異なります。

どの行を安全に削除することができるかを判断するために、システムはシステムで実行されている最も古いアク

ティブ トランザクションのタイムスタンプを追跡し、この値を使用して、どの行がまだ必要とされている可能性がある

かを判断します。この時点で有効でない行 (終了タイムスタンプがこの時刻よりも前である行) は、古いものとみ

なされます。古い行を削除し、メモリを解放してシステムに戻すことができます。

ガベージ コレクション システムは、非ブロッキングであり、協調性、効率性、応答性、および拡張性を備えるよう

に設計されています。特に興味深いのは “協調” 属性です。ガベージ コレクション処理専用のシステム スレッド

が存在しますが、実際にはユーザー スレッドが作業の大半を実行します。ユーザー スレッドがインデックスをス

キャンしていて (かつメモリ最適化テーブルでのすべてのインデックス アクセスがスキャン中であるとみなされていて)、

古い行バージョンに遭遇した場合、そのバージョンを現在のチェーンからリンク解除し、ポインターを調整します。

また、行ヘッダー領域で参照カウントを減らします。さらに、ユーザー スレッドはトランザクションを完了するときに、

そのトランザクションに関する情報をガベージ コレクション処理によって処理されるトランザクションのキューに追加

します。最後に、ガベージ コレクション スレッドによって作成されるキューから 1 つ以上の作業項目を選択し、そ

の作業項目を構成する行によって使用されているメモリを解放します。

ガベージ コレクション スレッドは、約 1 分ごとに完了済みトランザクションのキューを調べますが、システムは処理

を待機している完了済みトランザクションの数に基づいて内部で頻度を調整できます。各トランザクションから、ど

の行が古いかを判断し、削除の準備ができている行のセットで構成される作業項目を構築します。CTP2 では、

セット内の行数は 16 ですが、その数は将来のバージョンで変更されることがあります。これらの作業項目は、複

数のキュー (SQL Server によって使用される CPU ごとに 1 つ) に分散されます。通常、メモリから行を実際

に削除する作業は、キューからのこれらの作業項目を処理するユーザー スレッドに任されますが、ユーザー アク

ティビティがほとんどない場合は、ガベージ コレクション スレッドそのものが行を削除してシステム メモリを再要求

することができます。

Page 34: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

34

DVM sys.dm_db_xtp_index_stats には各メモリ最適化テーブル上の各インデックスの行が含まれます。

また、列 rows_expired は、そのインデックスのスキャン中に古いものであるとして検出された行の数を示しま

す。そのインデックスからリンク解除された行の数を示す row_expired_removed という列もあります。既に

説明したように、行がテーブル上のすべてのインデックスからリンク解除されると、ガベージ コレクション スレッドに

よって削除できるようになります。したがって、メモリ最適化テーブル上のすべてのインデックスの rows_expired

カウンターが増えるまで、row_expired_removed 値は増えません。

次のクエリで、これらの値を確認することができます。sys.dm_db_xtp_index_stats DMV を

sys.indexes カタログ ビューと結合して、インデックスの名前を返すことができるようにします。

SELECT name AS 'index_name', s.index_id, scans_started, rows_returned,

rows_expired, rows_expired_removed

FROM sys.dm_db_xtp_index_stats s JOIN sys.indexes i

ON s.object_id=i.object_id and s.index_id=i.index_id

WHERE object_id('<memory-optimized table name>') = s.object_id;

GO

トランザクション分離および同時実行制御管理

既に説明したように、メモリ最適化テーブルでのデータのすべてのアクセスは、完全にオプティミスティックな同時実

行制御を使用して行われますが、複数のトランザクション分離レベルは許可されます。ただし、どの分離レベルが

どのような状況で許可されるかは、少し混乱を招き、直感的でないように見える場合があります。懸念すべき分

離レベルは、クロス コンテナ トランザクションが関与する分離レベルです。これは、明示的または暗示的なトラ

ンザクションから実行されたか、オートコミット モードで実行されたかにかかわらず、メモリ最適化テーブルを参照す

るすべての変換されたクエリを意味します。クロス コンテナ トランザクションにおいてメモリ最適化テーブルで使用

できる分離レベルは、トランザクションが SQL Server トランザクションに対してどの分離レベルを定義しているか

によって決まります。制限のほとんどは、ディスク ベース テーブルに対する操作とメモリ最適化テーブルに対する操

作が同じ Transact-SQL トランザクションでアクセスされる場合であっても、それぞれ独自のトランザクション

シーケンス番号を持つという事実に関係します。この動作は、より大きなトランザクション内に 2 つのサブトランザ

クションがあると考えることができます。1 つのサブスクリプションはディスク ベース テーブル用で、1 つはメモリ最適

化テーブル用です。

最初に、一般的な分離レベルに関する背景を少し説明しましょう。これは分離レベルに関する完全な説明では

ありません。完全な説明はこのホワイトペーパーの範囲を越えています。分離レベルは、保証することができる整

合性プロパティという観点で定義できます。最も重要なプロパティは次のとおりです。

Page 35: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

35

1. 読み取りの安定性。T がレコードの処理中にそのレコードのバージョン V1 を読み取る場合、トランザク

ションの終了時点で V1 が依然として T から見えるバージョンであること (V1 が別のコミットされたバー

ジョン V2 によって置き換えられていないこと) が保証される必要があります。これは、V1 を読み取り

ロックして更新を防止するか、V1 がコミット前に更新されていないことを検証することによって実装でき

ます。

2. ファントムの回避。トランザクション T のスキャンが T の開始時刻と T のコミット時刻の間に追加された

新しいバージョンを返さないことを保証できる必要があります。これは、インデックス/テーブルのスキャン済

み部分をロックするか、コミット前に新しいバージョンがあるかどうかを再スキャンしてチェックすることによっ

て実装できます。

次に、これらのプロパティに基づいてトランザクション分離レベルを定義できます。最初の分離レベル

(SNAPSHOT) ではこれらのプロパティは言及されませんが、あとの 2 つでは言及されています。

SNAPSHOT

この分離レベルでは、トランザクション内のステートメントによって読み取られるデータがトランザクションの

開始時に存在していたデータのトランザクションの観点で整合したバージョンであることが規定されていま

す。トランザクションは、トランザクションの開始前にコミットされていたデータ変更のみを認識できます。現

在のトランザクションの開始後に他のトランザクションによって加えられたデータ変更は、現在のトランザク

ション内で実行されているステートメントからは見えません。コミットされたデータがトランザクションの開始

時に存在していたとき、トランザクション内のステートメントはそのデータのスナップショットを取得します。

REPEATABLE READ

この分離レベルには、SNAPSHOT 分離レベルによって提供される保証が含まれます。さらに、

REPEATABLE READ は、読み取りの安定性を保証します。トランザクションによって読み取られる行

については、トランザクションがコミットする時点では、その行は他のトランザクションによって変更されてい

ません。トランザクション内のすべての読み取り操作は、トランザクションの終了まで反復可能です。

SERIALIZABLE

この分離レベルには、REPEATBLE READ 分離レベルによって提供される保証が含まれます。さらに、

SERIALIZABLE はファントムの回避を保証します。トランザクション内の操作は、どの行も見落として

いません。スナップショットの時点からトランザクションの終了までの間にファントム行は現れていません。

ファントム行は、SELECT/UPDATE/DELETE のフィルター条件に合致します。すべての読み取りが

トランザクションの終了時に繰り返されたときにまったく同じデータを参照することを保証できる場合、トラ

ンザクションはシリアル化可能となります。

Page 36: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

36

最も簡単で最も幅広く使用されている MVCC 方法は、スナップショット分離 (SI) ですが、SI はシリアル化可

能性を保証しません。読み取りがトランザクションの最初、書き込みが最後というように読み取りと書き込みが論

理的に異なる時点で発生するためです。

ディスク ベース テーブルへのアクセスでも READ COMMITTED 分離がサポートされ、トランザクションがダー

ティ (コミットされていない) データを読み取らないことを保証します。メモリ最適化テーブルへのアクセスは、前述

の 3 つの分離レベルのいずれかを使用する必要があります。クロス コンテナ トランザクションで使用できる分離

レベルの組み合わせを表 1 に示します。

ディスク ベース テーブル メモリ最適化テーブル 推奨事項

READ COMMITTED SNAPSHOT これはベースラインの組み合わせです。現時

点では、READ COMMITTED を使用する

ほとんどの状況で使用する必要があります。

READ COMMITTED REPEATABLE READ /

SERIALIZABLE

この組み合わせは、(ネイティブにコンパイルさ

れたプロシージャではなく) データ移行中、お

よび相互運用モードでのメモリ最適化テーブ

ル アクセスに使用できます。

REPEATABLE READ /

SERIALIZABLE

SNAPSHOT メモリ最適化テーブルのアクセスは、INSERT

操作のみです。この組み合わせも移行中、お

よびメモリ最適化テーブルで同時書き込み操

作が実行されていない場合に役立つことがあ

ります。

SNAPSHOT - メモリ最適化テーブル アクセスは許可されま

せん (注 1 を参照してください)

REPEATABLE READ /

SERIALIZABLE

REPEATABLE READ /

SERIALIZABLE

この組み合わせは許可されません (注 2 を

参照してください)

表 1: クロス コンテナ トランザクションでの互換性のある分離レベル

注 1: SNAPSHOT 分離の場合、すべての操作は、トランザクションの開始時点で存在していたデータのバー

ジョンを参照する必要があります。SNAPSHOT の場合、トランザクションの開始は、最初のテーブルがアクセス

されるときに測定されます。ただし、クロス コンテナ トランザクションでは、サブトランザクションがそれぞれ異なる時

点で開始できるため、別のトランザクションが 2 つのサブトランザクションの開始時点の間にデータを変更した可

能性があります。クロス コンテナ トランザクションは、スナップショットの基になる 1 つの時点を持たなくなります。

Page 37: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

37

注 2: 両方のサブトランザクション (ディスク ベース テーブル上の 1 つとメモリ最適化テーブル上の 1 つ) が

REPEATABLE READ または SERIALIZABLE を使用できないのは、2 つのシステムが分離レベルを異な

る方法で実装するからです。図 9 に示す 2 つのクロス コンテナ トランザクションを考えてみます。

時間 Tx1 (SERIALIZBLE) Tx2 (任意の分離レベル)

1 BEGIN SQL/In-Memory sub-xacts 2 Read RHk1 3 BEGIN SQL/In-Memory sub-

transactions 4 Read RSql1 and update to RSql2 5 Read RHk1 and update to RHk2 6 COMMIT 7 Read RSql2

図 9: 2 つの同時実行クロス コンテナ トランザクション

Tx1 は、最初にメモリ最適化テーブルから行を読み取ります。ロックは保持されないため、Tx2 は完了し、2 つ

の行を変更できます。Tx1 が再開され、ディスク ベース テーブルから行を読み取るとき、トランザクションが分離

して実行される場合 (トランザクションが真にシリアル化可能な場合) には決して存在することができなかった 2

つの行の値セットが存在します。そのため、この組み合わせは許可されません。

分離レベルの詳細については、以下を参照してください。

http://en.wikipedia.org/wiki/Isolation_(database_systems)

http://research.microsoft.com/apps/pubs/default.aspx?id=69541

チェックポイントと回復

SQL Server は、メモリ最適化テーブルのトランザクションの永続性を確保して、障害発生後に変更を回復で

きるようにする必要があります。インメモリ OLTP は、チェックポイント処理とトランザクション ログ処理の両方が

永続ストレージに書き込むようにすることで、これを実現します。このホワイト ペーパーでは取り上げませんが、イ

ンメモリ OLTP は、フェールオーバーをサポートする高可用性レプリカを維持する AlwaysOn 可用性グループ

機能とも統合されています。

ディスクに書き込まれる情報は、チェックポイント ストリームとトランザクション ログ ストリームで構成されます。

ログ ストリームには、行バージョンの挿入および削除としてログ記録されたコミット済みトランザクションに

よって加えられた変更が含まれます。

チェックポイント ストリームには 2 つの種類がああります。

o データ ストリームには、タイムスタンプ間隔の間に挿入されたすべてのバージョンが含まれます。

Page 38: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

38

o デルタ ストリームは、特定のデータ ストリームと関連付けられていて、その対応するデータ スト

リーム内のどのバージョンが削除されたかを示す整数の一覧を含みます。

メモリ最適化テーブルのインメモリ状態をトランザクションの観点で整合している時点へと回復するには、トランザ

クション ログとチェックポイント ストリームの内容の組み合わせで十分です。ログ ファイルとチェックポイント ファイル

がどのように生成されて使用されるかについて詳しく説明する前に、注意すべき重要な点をいくつか示します。

ログ ストリームは、標準の SQL Server トランザクション ログに格納されます。

チェックポイント ストリームは、基本的には SQL Server によって完全に管理されるシーケンシャル ファ

イルである SQL Server FILESTREAM ファイルに格納されます (FILESTREAM ストレージは

SQL Server 2008 で導入されました。インメモリ OLTP チェックポイント ファイルはそのテクノロジを

活用します。FILESTREAM ストレージの詳細および管理については、

http://msdn.microsoft.com/ja-jp/library/hh461480.aspx にあるホワイト ペーパーを参

照してください)。

トランザクション ログには、トランザクションを再実行するために十分な、コミット済みトランザクションに関

する情報が含まれています。変更は、行バージョンの挿入および削除として記録され、その行バージョン

が属するテーブルでマークされます。トランザクション ログには元に戻す操作に関する情報は書き込まれ

ません。

メモリ最適化テーブルに対するインデックス操作はログ記録されません。すべてのインデックスは、回復時

に完全に再構築されます。

トランザクション ログ

インメモリ OLTP のトランザクション ログは、拡張性と高パフォーマンスの両方を実現するように設計されていま

す。各トランザクションは、SQL Server の標準のトランザクション ログに書き込まれる大きなログを最小限の数

だけ使用してログ記録されます。ログ レコードには、トランザクションによって挿入および削除されたすべてのバー

ジョンに関する情報が含まれます。この情報を使用して、トランザクションを回復時に再実行できます。

インメモリ OLTP トランザクションの場合、ログ レコードはコミット時にのみ生成されます。インメモリ OLTP は、

ディスク ベース テーブルで操作を処理するときに使用されるような、先書きログ (WAL) を使用しません。WAL

では、SQL Server は、変更されたデータをディスクに書き込む前にログに書き込みます。これは、チェックポイン

ト中に書き出されたコミットされていないデータに対しても発生することがあります。インメモリ OLTP の場合、

ダーティ データがディスクに書き込まれることはありません。さらに、インメモリ OLTP は、複数のログ レコードを 1

つの大きな I/O にグループ化しようとします。WAL を使用しないことは、インメモリ OLTP コミット処理を非常

に効率的なものにすることができる要素の 1 つです。

Page 39: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

39

インメモリ OLTP は、データベースごとに同時に生成される複数のログ ストリームをサポートして、ログの末尾に

よるスケーリング ボトルネックを回避するように設計されています。シリアル化の順序はトランザクション ログ内の

順序付けではなく、トランザクションの終了タイムスタンプによってのみ判断されるので (上記を参照)、複数のロ

グ ストリームを使用できます。ただし、SQL Server 2014 の場合、SQL Server とのインメモリ OLTP 統合

は、データベースごとにログ ストリームを 1 つだけ利用します (SQL Server のログ ファイルはデータベースごとに

1 つだけであるため)。現在のテストでは、これは問題となっていません。ディスク ベース テーブルでの操作と比較

してインメモリ OLTP が生成するログ データははるかに小さく、ログ書き込みははるかに少ないためです。

次の簡単なスクリプトは、メモリ最適化テーブルで大幅に削減されたログを示しています。このスクリプトは、メモリ

最適化テーブルを保持できるデータベースを作成し、2 つの同様のテーブルを作成します。1 つはメモリ最適化

テーブルで、1 つはディスク ベース テーブルです。

USE master

GO

IF EXISTS (SELECT * FROM sys.databases WHERE name='LoggingDemo')

DROP DATABASE LoggingDemo;

GO

CREATE DATABASE LoggingDemo ON

PRIMARY (NAME = [LoggingDemo_data], FILENAME =

'C:\DataHK\LoggingDemo_data.mdf'),

FILEGROUP [LoggingDemo_FG] CONTAINS MEMORY_OPTIMIZED_DATA

(NAME = [LoggingDemo_container1], FILENAME =

'C:\DataHK\StorageDemo_mod_container1')

LOG ON (name = [hktest_log], Filename='C:\DataHK\StorageDemo.ldf',

size=100MB);

GO

USE LoggingDemo

GO

IF EXISTS (SELECT * FROM sys.objects WHERE name='t1_inmem')

DROP TABLE [dbo].[t1_inmem]

GO

-- create a simple memory-optimized table

CREATE TABLE [dbo].[t1_inmem]

( [c1] int NOT NULL,

[c2] char(100) NOT NULL,

CONSTRAINT [pk_index91] PRIMARY KEY NONCLUSTERED HASH ([c1])

WITH(BUCKET_COUNT = 1000000)

) WITH (MEMORY_OPTIMIZED = ON,

DURABILITY = SCHEMA_AND_DATA);

GO

IF EXISTS (SELECT * FROM sys.objects WHERE name='t1_disk')

DROP TABLE [dbo].[t1_disk]

GO

-- create a similar disk-based table

CREATE TABLE [dbo].[t1_disk]

( [c1] int NOT NULL,

[c2] char(100) NOT NULL)

GO

Page 40: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

40

CREATE UNIQUE NONCLUSTERED INDEX t1_disk_index on t1_disk(c1);

GO

次に、ディスク ベース テーブルに 100 行を読み込み、ドキュメント化されていない (サポートされていない) 関

数 fn_dblog() を使用してトランザクション ログの内容を調べます。

BEGIN TRAN

DECLARE @i int = 0

WHILE (@i < 100)

BEGIN

INSERT INTO t1_disk VALUES (@i, replicate ('1', 100))

SET @i = @i + 1

END

COMMIT

-- you will see that SQL Server logged 200 log records

SELECT * FROM sys.fn_dblog(NULL, NULL)

WHERE PartitionId IN

(SELECT partition_id FROM sys.partitions

WHERE object_id=object_id('t1_disk'))

ORDER BY [Current LSN] ASC;

GO

次に、メモリ最適化テーブルで同様な更新を実行します。図 10 のように、ログが 3 つだけ表示されます。

BEGIN TRAN

DECLARE @i int = 0

WHILE (@i < 100)

BEGIN

INSERT INTO t1_inmem VALUES (@i, replicate ('1', 100))

SET @i = @i + 1

END

COMMIT

-- look at the log

SELECT * FROM sys.fn_dblog(NULL, NULL) order by [Current LSN] DESC;

GO

図 10: 100 行のトランザクションに対する 1 つのログ レコードを示す SQL Server トラン

ザクション ログ

出力は、すべての 100 の挿入が種類 LOP_HK の単一のログ レコードにログ記録されたことを示しています。

LOP は、”論理操作” を示していて、HK は、プロジェクト コードネーム Hekaton を表しています。もう 1 つの

Page 41: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

41

ドキュメント化およびサポートされていない関数を使用して、LOP_HK レコードを分解できます。LSN 値を自身

の LOP_HK レコード用の LSN に置き換える必要があります。

SELECT [current lsn], [transaction id], operation,

operation_desc, tx_end_timestamp, total_size,

object_name(table_id) AS TableName

FROM sys.fn_dblog_xtp(null, null)

WHERE [Current LSN] = '00000020:00000157:0005';

出力の最初の数行は図 11 のようになります。

図 11: メモリ最適化テーブルでの挿入のログ レコードを分解して示される影響を受けた個々

の行

メモリ最適化テーブルでのトランザクション全体に対する単一のログ レコード、およびログ記録される情報のサイ

ズの削減により、メモリ最適化テーブルでのトランザクションがはるかに効率的になります。

チェックポイント

ディスク ベース テーブルでの操作の場合と同様、チェックポイント操作の主な理由の 1 つは回復時間の短縮で

す。メモリ最適化テーブルのチェックポイント処理は、2 つの重要な要件を満たすように設計されています。

継続的なチェックポイント処理。チェックポイント関連の I/O 操作は、トランザクション アクティビティの

累積に伴い、増分的かつ継続的に発生します。ハイパーアクティブ チェックポイント スキーム (しばらく

の間スリープし、その後、ウェイクアップして可能な限り集中的に作業して累積された作業を完了する

チェックポイント処理として定義されています) は、システムの全体的なパフォーマンスを妨害する可能

性があります。

ストリーミング I/O。チェックポイント処理は、ほとんどの操作において、ランダム I/O ではなくストリーミ

ング I/O を使用します。SSD デバイスであっても、ランダム I/O はシーケンシャル I/O よりも低速であ

り、より小さな個々の I/O 要求が原因で多くの CPU オーバーヘッドを招く可能性があります。

メモリ最適化テーブルのチェックポイント操作は、4 つの異なるシナリオで呼び出されます。

Page 42: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

42

手動チェックポイント: 明示的な CHECKPOINT コマンドが発行されるときに、ディスク ベース テーブ

ルとメモリ最適化テーブルの両方でチェックポイント操作を開始します。

ディスク ベース テーブルまたはメモリ最適化テーブルでのトランザクション アクティビティがない場合: この

場合、インメモリ OLTP エンジンは、メモリ最適化テーブルに対して時間ベースのチェックポイントを実行

し、ストレージに 128 MB のファイルを追加します。現時点では、その間隔は 6 時間ごとです。インメ

モリ OLTP エンジンは、これらのファイルでマージ操作を実行して、ファイルの数が無限に増え続けない

ようにします。チェックポイント ファイルのマージ操作については、以下で説明します。

メモリ最適化テーブルで多くのアクティビティがあるが、ディスク ベース テーブルではまったく (またはほとん

ど) アクティビティがない場合、またはメモリ最適化テーブルではまったく (またはほとんど) アクティビティが

ないが、ディスク ベース テーブルでは多くのアクティビティがある場合: インメモリ OLTP チェックポイント

は、ログのサイズが最後のチェックポイント以降に 1 GB 増加したときに実行されます。この場合、チェッ

クポイントはログ サイズに基づいているので、メモリ最適化テーブルによって生成されるログにより、SQL

Server エンジンはチェックポイントを実際に起動します。したがって、ログの切り捨てポイントは、SQL

Server とインメモリ OLTP の両方で前進します。

チェックポイント ファイル

チェックポイント データは、データ ファイルとデルタ ファイルの 2 種類のチェックポイント ファイルに格納されます。

完全なチェックポイントは、複数のデータ ファイルとデルタ ファイル、およびチェックポイントを構成するファイルをリス

トするチェックポイント ファイル インベントリで構成されます。

データ ファイルには、挿入されたバージョンまたは行のみが含まれます。既に確認したとおり、これらは INSERT

操作と UPDATE 操作の両方によって生成されます。各ファイルは、特定のタイムスタンプ範囲をカバーします。

データ ファイルの範囲内の開始タイムスタンプを持つすべてのバージョンがファイルに含まれます。データ ファイルは、

開かれているときは追加専用で、閉じられた後は、厳密に読み取り専用となります。回復時、データ ファイル内

の有効なバージョンがメモリに再度読み込まれ、インデックスが再設定されます。

デルタ ファイルは、データ ファイルに含まれているどのバージョンがその後削除されたかについての情報を格納し

ます。デルタ ファイルとデータ ファイルは 1 対 1 で対応します。デルタ ファイルは、対応するデータ ファイルが有

効な間は追加専用です。回復時、デルタ ファイルは、削除済みのバージョンをメモリに再度読み込むのを回避

するためのフィルターとして使用されます。各データ ファイルは 1 つのデルタ ファイルとペアになっているため、回復

の最小作業単位はデータ/デルタ ファイルのペアです。これにより、回復処理が大幅に並列処理可能になります。

チェックポイント ファイル インベントリには、完全なチェックポイントを構成するすべてのデータ ファイルおよびデル

タファイルへの参照が含まれます。インベントリはトランザクション ログに書き込まれます。

Page 43: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

43

完全なチェックポイントがトランザクション ログの末尾と組み合わされることで、メモリ最適化テーブルの回復が可

能になります。チェックポイントにはタイムスタンプがあります。つまり、チェックポイント タイムスタンプよりも前のすべ

てのトランザクションの結果がチェックポイントに記録されるため、回復するためにトランザクション ログは不要です。

チェックポイント処理

チェックポイント タスクは、前のチェックポイントではカバーされていないトランザクション ログのセクションを取り入れ、

ログのそのセクションに含まれているメモリ最適化テーブルに対するすべての操作を 1 つ以上のデータ ファイルお

よびデルタ ファイルに変換します。新しい行バージョンは、最新のデータ ファイルまたは新しいデータ ファイルに追

加され、削除されたバージョンの ID はデルタ ファイルに追加されます。チェックポイント タスクがログの処理を完

了すると、チェックポイントは次のステップによって完了します。

1. バッファーに入れられたすべての書き込みがデータ ファイルおよびデルタ ファイルにフラッシュされます。

2. チェックポイント インベントリが構築され、前のチェックポイントからのすべてのファイルおよび現在のチェック

ポイントによって追加されるファイルの記述子が含まれます。インベントリは、トランザクション ログに書き

込まれます。

3. 回復時に利用できるよう、インベントリの場所がトランザクションログに格納されます。

チェックポイント ファイルのマージ

チェックポイントに含まれるファイルのセットは、チェックポイントごとに増加します。ただし、データ ファイルのアクティ

ブ コンテンツは、対応するデルタ ファイルでますます多くのバージョンが削除済みとしてマークされるにつれて減少

します。回復処理はチェックポイント内のすべてのデータ ファイルおよびデルタ ファイルの内容を読み取るため、各

データ ファイル内の関連する行数が減少するにつれ、クラッシュ回復のパフォーマンスは低下します。

この問題の解決策は、アクティブ コンテンツ (データ ファイル内の削除されていないバージョンの割合) がしきい

値を下回ったときにタイムスタンプ範囲の観点で隣接しているデータ ファイルをマージすることです。2 つのデータ

ファイル DF1 および DF2 をマージすると、DF1 および DF2 を組み合わせた範囲をカバーする新しいデータ

ファイル DF3 が作成されます。DF1 および DF2 のデルタ ファイルで識別されるすべての削除済みバージョン

は、マージ中に削除されます。DF3 のデルタ ファイルは、マージ操作開始後に発生した削除を除き、マージ後

直ちに空になります。

マージは、2 つの隣接するデータ ファイルがそれぞれ 50% フル未満である場合にも発生することがあります。手

動チェックポイントが実行された場合 (現在開かれているチェックポイント データ ファイルを閉じ、新しいデータ

ファイルを開始する場合)、データ ファイルは最後に部分的にのみフルになることがあります。

Page 44: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

44

自動マージ

マージされるファイルを識別するために、バックグランド タスクは定期的にすべてアクティブなデータ/デルタ ファイル

のペアを調べ、対象となる 0 個以上のファイル セットを識別します。各セットには、結果として得られる行セット

がサイズ 128MB の単一のデータ ファイルに収まることができるように、互いに隣接している 2 つ以上のデータ/

デルタ ファイルのペアを含めることができます。図 12 は、マージ ポリシーに従ってマージするように選択されるファ

イルの例を示しています。

隣接するソース ファイル (% フル) マージ選択

DF0 (30%) DF1 (50%)、DF2 (50%), DF3 (90%) (DF1、DF2)

DF0 (30%) DF1 (20%)、DF2 (50%), DF3 (10%) (F0、 F1、F2)。ファイルは左から選択されます。

DF0 (80%), DF1 (10%)、DF2 (10%), DF3(20%) (DF0、DF1、DF2)。ファイルは左から選択されます。

図 12: ファイル マージ操作に選択できるファイルの例

2 つの隣接するデータ ファイルが 60% フルである場合、これらはマージされず、ストレージの 40% は未使用

です。したがって事実上、永続性のあるメモリ最適化テーブルに使用される合計ディスク ストレージは、対応す

るメモリ最適化サイズよりも大きくなります。最悪の場合、永続テーブルによって占められるストレージ領域のサイ

ズは、対応するメモリ最適化サイズの 2 倍よりも大きくなることがあります。

sys.sp_xtp_merge_checkpoint_files の手動マージ

ほとんどの場合、ファイルの数を管理可能な数に保つには、チェックポイント ファイルの自動マージで十分です。し

かし、テスト目的などで手動マージの使用が必要になる場合があります。プロシージャ

sp_xtp_merge_checkpoint_files は、チェックポイント ファイルの手動マージを強制します。どのファイルが

対象であるかを判断するには、sys.dm_db_xtp_checkpoint_files でメタデータを確認できます。メタデー

タは図 13 のようになっています。

Page 45: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

45

図 13: sys.dm_db_xtp_checkpoint_files からのメタデータ

この情報から、フルではない隣接するファイルを見つけ、最初のファイルの transaction_id_lower_bound

および 最後のファイルの transaction_id_lower_bound を特定できます。図 13 の出力では、

file_size_in_bytes 値を file_size_used_in_bytes 値と比較するとわかるように、最初の数個のアクティ

ブ ファイルはほぼフルです。しかし、領域を 136K しか使用していないファイルが 10 個あり、各ファイルには

1000 行しか挿入されていません。これらの最初の 5 個をマージする場合、最初のファイルの

transaction_id_lower_bound (0x40000000000186A5) および最後のファイルの

transaction_id_lower_bound (0x4000000000019A37) が必要になります。次にプロシージャを呼

び出します。

EXEC sys.sp_xtp_merge_checkpoint_files 'InMemory_DB', 0x40000000000186A5,

0x4000000000019A37;

GO

別の DMV でマージ操作の状態を確認できます。

SELECT * FROM sys.dm_db_xtp_merge_requests;

GO

出力は図 14 のようになります。

図 14: 保留中のマージ操作

注目すべきは、図 13 では、ファイルの現在の一覧にマージ先の file_id が含まれていない点です。しかし、

sys.dm_db_xtp_checkpoint_files を調べると、その ID を持ち、合計 5000 行を含むファイルが見つか

ります。マージが完了すると、sys.dm_db_xtp_merge_requests の request_state_description 列

に値 INSTALLED が表示されます。

テスト目的で、ファイルのマージをオフにし、このメタデータを簡単に調べることができるようにする必要が生じる場

合があります。その場合、ドキュメント化されていないトレース フラグ 9851 をオンにします。テストが完了した後

は、このトレース フラグを必ずオフにしてください。

チェックポイント ファイルのガベージ コレクション

マージ操作が完了すると、ソース ファイルは不要になり、標準のログ バックアップが取られている限り、後でガベー

ジ コレクションによって削除することができます。チェックポイント ファイルを削除する前に、インメモリ OLTP エン

ジンは、それが必要とされないことを確認する必要があります。一般に、ガベージ コレクション処理は自動で、介

Page 46: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

46

入を必要としません。しかし、未使用のチェックポイント ファイルのガベージ コレクションを強制的に実行するため

のオプションがあります。

ファイルは、ガベージ コレクション処理によって実際に削除される前に 3 つのステージを通過する必要があります。

ファイル A (データ/デルタ)、B (データ/デルタ) を C (データ/デルタ) にマージするとします。主なステップを以下

に示します。

ステージ 1: マージが完了した後、2 つの明示的な手動チェックポイント操作を実行する必要がありま

す。これでファイル A および B 内のデータが回復に必要でないことが保証されます。

ステージ 2: ログの切り捨てポイントが、ファイル A および B が必要になる位置を越えたポイントへと安

全に移動したことを保証する必要があります。以下の 3 つのステップを 2 度実行します。(SIMPLE

回復モデルを使用するデータベースの場合、ログ バックアップは不要です)。このステージの後、ファイル

はインメモリ データベース エンジンから sys.dm_db_xtp_checkpoint_files DMV を通じて見るこ

とができなくなりますが、ディスクでは表示されます。

o 手動チェックポイントを実行

o トランザクション ログをバックアップ

o プロシージャ sp_xtp_checkpoint_force_garbage_collection を実行

ステージ 3: 標準の FILESTREAM ファイルの場合と同じメカニズムを使用して、ファイル A および B

をシステム ガベージ コレクション処理によって削除することができます。ステージ 2 と同様、一連のス

テップを 2 度実行する必要があります。

o 手動チェックポイントを実行

o トランザクション ログをバックアップ

o プロシージャ sp_force_filestream_garbage_collection を実行

ステップ 3 の後、ファイルはオペレーティング システムから見えなくなります。ここに示すファイルの手動ガベージ コ

レクションを実装する必要がある場合は、実行されたこれらの追加のトランザクション ログ バックアップに対する

説明責任を確認する必要があります。また、サードパーティ製のバックアップ ソリューションがこれらのログ バック

アップ ファイルを認識することを確認する必要があります。または、この手動のガベージ コレクションを実行した後

で完全なデータベース バックアップを実行して、以降のトランザクション ログ バックアップがそれを開始ポイントとし

て使用するようにすることができます。

Page 47: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

47

回復

インメモリ OLTP テーブルでの回復は、ログの末尾のスキャン中に最新のチェックポイント インベントリの位置が

回復された後で開始します。SQL Server ホストがチェックポイント インベントリの位置をインメモリ OLTP エン

ジンに通信すると、SQL Server およびインメモリ OLTP 回復が並行して進みます。

インメモリ OLTP 回復そのものが並列化されます。各デルタ ファイルは、対応するデータ ファイルから読み込ま

れる必要のない行に対するフィルターを表します。このデータ/デルタ ファイルのペア配置は、チェックポイントの読

み込みを複数の IO ストリーム間で並行して進めることができ、各ストリームが単一のデータ ファイルおよびデル

タ ファイルを処理することを意味します。挿入スレッドは、削除された行を削除した後、データ ファイル内のすべ

てのアクティブな行をメモリに読み込みます。コアあたり 1 つのスレッドの選択は、読み込み処理ができる限り効

率的に実行されることを意味します。

最後に、チェックポイント読み込みプロセスが完了すると、データベースをクラッシュ時点に存在した状態に戻すた

めに、トランザクション ログの末尾がチェックポイントのタイムスタンプから再生されます。

テーブルおよびストアド プロシージャのネイティブ コンパイル

インメモリ OLTP は、ネイティブ コンパイルの概念を SQL Server 2014 に導入します。SQL Server は、メ

モリ最適化テーブルにアクセスするストアド プロシージャをネイティブにコンパイルできます。実際、メモリ最適化

テーブル自身もネイティブにコンパイルします。ネイティブ コンパイルにより、従来の変換された Transact-SQL

が提供するよりも迅速なデータ アクセスと効率的なクエリ実行が可能になります。

ネイティブ コンパイル

ネイティブ コンパイルとは、プログラミング コンストラクトをネイティブ コードに変換する処理のことで、CPU によっ

て直接実行できるプロセッサ命令で構成されていて、追加のコンパイルや変換を必要としません。

Transact-SQL 言語は、CREATE TABLE や SELECT … FROM などのハイレベルのコンストラクトで構

成されます。インメモリ OLTP コンパイラは、これらのコンストラクトを取り入れ、ネイティブ コードへとコンパイルし

て、高速の実行時データ アクセスとクエリ実行を実現します。SQL Server 2014 のインメモリ OLTP コンパ

イラは、テーブルおよびストアド プロシージャ定義を入力として取り入れます。C コードを生成し、Visual C コン

パイラを利用してネイティブ コードを生成します。

テーブルおよびストアド プロシージャのコンパイルの結果は、メモリに読み込まれ、SQL Server プロセスにリンク

される DLL です。

SQL Server は、メモリ最適化テーブルとネイティブにコンパイルされたストアド プロシージャの両方を作成時に

ネイティブ DLL にコンパイルします。さらに、テーブルおよびストアド プロシージャ DLL は、データベースまたは

Page 48: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

48

サーバーの再起動後に再コンパイルされます。DLL を再作成するために必要な情報はデータベース メタデータ

に格納されます。DLL そのものはデータベースの一部ではありません。したがって、たとえば、DLL はデータベース

バックアップには含まれません。

DLL の保守

メモリ最適化テーブルおよびネイティブにコンパイルされたストアド プロシージャの DLL は、他の生成されたファイ

ルと共に、ファイルシステムに格納されます。これらはトラブルシューティングおよびサポート目的で保持されます。

以下のクエリは、サーバーのメモリに現在読み込まれているすべてのテーブルおよびストアド プロシージャ DLL を

表示します。

SELECT name, description FROM sys.dm_os_loaded_modules WHERE description = 'XTP Native DLL'

データベース管理者は、ネイティブ コンパイルによって生成されるファイルを保守する必要はありません。SQL

Server は、テーブルおよびストアド プロシージャの削除時、データベースの削除時、サーバーまたはデータベー

スの再起動時などに、不要になった生成済みファイルを自動的に削除します。

テーブルのネイティブ コンパイル

CREATE TABLE ステートメントを使用してメモリ最適化テーブルを作成すると、テーブル情報はメモリ内で作

成されるデータベース メタデータ、テーブル、およびインデックス構造に書き込まれ、さらにテーブルが DLL にコン

パイルされます。

以下のサンプル スクリプトを考えてみます。このスクリプトは、データベースおよび単一のメモリ最適化テーブルを

作成します。

USE master GO create database db1 GO ALTER DATABASE db1 ADD FILEGROUP db1_mod CONTAINS memory_optimized_data GO -- adapt filename as needed ALTER DATABASE db1 ADD FILE (name='db1_mod', filename='c:\data\db1_mod') TO FILEGROUP db1_mod GO USE db1 GO CREATE TABLE dbo.t1 (c1 int not null primary key nonclustered, c2 int) WITH (MEMORY_OPTIMIZED=ON) GO -- retrieve the path of the DLL for table t1 SELECT name, description FROM sys.dm_os_loaded_modules WHERE name LIKE '%xtp_t_' + cast(db_id() AS varchar(10)) + '_' + cast(object_id('dbo.t1') AS varchar(10)) + '.dll' GO

Page 49: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

49

テーブル作成により、テーブル DLL のコンパイルが発生し、その DLL がメモリに読み込まれます。DMV は、

CREATE TABLE ステートメントがテーブル DLL のパスを取得した後すぐにクエリを行います。

t1 のテーブル DLL はテーブルのインデックス構造および行形式を理解します。SQL Server は、インデックス

のスキャン、行および行の内容の取得のために DLL を使用します。

ストアド プロシージャのネイティブ コンパイル

NATIVE_COMPILATION とマークされているストアド プロシージャはネイティブにコンパイルされます。つまり、

プロシージャ内の Transact-SQL ステートメントは、すべてネイティブ コードにコンパイルされ、パフォーマンス ク

リティカルなビジネス ロジックの効率的な実行を実現します。

以下のサンプル ストアド プロシージャを考えてみます。このストアド プロシージャは、前の例のテーブル t1 内に

行を挿入します。

CREATE PROCEDURE dbo.p1 WITH NATIVE_COMPILATION, SCHEMABINDING, EXECUTE AS OWNER AS BEGIN ATOMIC WITH (TRANSACTION ISOLATION LEVEL=snapshot, LANGUAGE=N'us_english') DECLARE @i int = 1000000 WHILE @i > 0 BEGIN INSERT dbo.t1 VALUES (@i, @i+1) SET @i -= 1 END END GO EXEC dbo.p1 GO -- reset DELETE FROM dbo.t1 GO

プロシージャ p1 の DLL は、テーブル t1 の DLL、およびインメモリ OLTP ストレージ エンジンと直接対話して、

可能な限りすばやく行を挿入できます。

インメモリ OLTP コンパイラは、クエリ オプティマイザーを利用して、ストアド プロシージャ内の各クエリの効率的

な実行プランを作成します。ネイティブにコンパイルされたストアド プロシージャの場合、クエリ実行プランは DLL

にコンパイルされます。SQL Server 2014 はネイティブにコンパイルされたストアド プロシージャの自動再コンパ

イルをサポートしないので、テーブル データへの変更は、新しいクエリ プランをストアド プロシージャ DLL に組み

込むことができるようにするために特定のプロシージャの削除および再作成を必要とする場合があります。ネイティ

ブにコンパイルされたストアド プロシージャは、サーバー再起動後、および AlwaysOn セカンダリへのフェール

Page 50: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

50

オーバー後の最初の実行時に再コンパイルされます。つまり、クエリ オプティマイザーは、その後ストアド プロシー

ジャ DLL へとコンパイルされる新しいクエリ プランを作成します。

コンパイルおよびクエリ処理

図 15 は、ネイティブにコンパイルされたストアド プロシージャのコンパイル処理を示しています。

Parser

Algebrizer

T-SQL Stored Procedure Query Optimizer Compiler Runtime

Processing flow and Query Trees

Processing flow with Optimized Query

PlansDLL

図 15: ストアド プロシージャのネイティブ コンパイル

1. ユーザーが CREATE PROCEDURE ステートメントを SQL Server に発行します

2. パーサーおよびノーマライザーが、プロシージャの処理フロー、およびストアド プロシージャ内の

Transact-SQL クエリのクエリ ツリーを作成します

3. オプティマイザーが、ストアド プロシージャ内のすべてのクエリに対して、最適化されたクエリ実行プランを

作成します。

4. インメモリ OLTP コンパイラが、処理フローを埋め込まれた最適化されたクエリ プランと共に取り入れ、

ストアド プロシージャを実行するためのマシン コードを含む DLL を生成します

5. 生成された DLL は、メモリに読み込まれ、SQL Server プロセスにリンクされます

図 16 に示すように、ネイティブにコンパイルされたストアド プロシージャの呼び出しは、DLL 内の関数へと変換

されます。

Parser

Algebrizer

Sproc invocationStored Proc DLL

In-MemoryStorage Engine

In-memory Storage

Get Row Read Row VersionParameters

Runtime

Sproc name

図 16: ネイティブにコンパイルされたストアド プロシージャの実行

Page 51: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

51

1. ユーザーが ‘EXEC myproc’ ステートメントを発行します

2. パーサーが名前およびストアド プロシージャ パラメーターを抽出します

3. インメモリ OLTP ランタイムが、ストアド プロシージャの DLL エントリ ポイントの位置を確認します

4. DLL がプロシージャ ロジックを実行し、結果をクライアントに返します

パラメーター スニッフィング

変換された Transact-SQL ストアド プロシージャは、最初の実行 (呼び出し) 時に中間の物理的な実行プ

ランにコンパイルされます。一方、ネイティブにコンパイルされたストアド プロシージャでは、作成時にネイティブにコ

ンパイルされます。変換されたストアド プロシージャが呼び出し時にコンパイルされる場合、この呼び出しに対し

て指定されたパラメーターの値は、実行プランを生成するときにオプティマイザーによって使用されます。このコンパ

イル中のパラメーターの使用は “パラメーター スニッフィング” と呼ばれます。

パラメーター スニッフィングは、ネイティブにコンパイルされたストアド プロシージャのコンパイルには使用されません。

ストアド プロシージャへのすべてのパラメーターは、UNKNOWN 値を持っているとみなされます。

SQL Server 機能のサポート

インメモリ OLTP およびメモリ最適化テーブルを含むデータベースでは、多くの SQL Server の機能がサポート

されていますが、すべての機能がサポートされているわけではありません。たとえば、AlwaysOn コンポーネント、

ログ シッピング、およびデータベースのバックアップと復元は完全にサポートされますが、データベース ミラーリングお

よびレプリケーションはサポートされません。SQL Server Management Studio を使用すればメモリ最適化

テーブルを扱うことができ、SSIS もサポートされます。

サポートされている機能とサポートされていない機能の一覧については、SQL Server インメモリ OLTP の該

当するドキュメントを参照してください。

管理エクスペリエンス

インメモリ OLTP は SQL Server の管理エクスペリエンスに完全に統合されています。既に説明したように、

SQL Server Management Studio はメモリ最適化テーブル、ファイルグループ、およびネイティブにコンパイ

ルされたプロシージャを扱うことができます。さらに、Server Management Object (SMO) および

PowerShell を使用して、メモリ最適化オブジェクトを管理できます。

Page 52: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

52

メタデータ

既存のメタデータ オブジェクトのいくつかが拡張され、メモリ最適化テーブルおよびプロシージャに関する情報が提

供されています。また、新しいオブジェクトが追加されました。

次の関数が拡張されています。

OBJECTPROPERTY – プロパティ TableIsMemoryOptimized が追加されました

カタログ ビュー

以下のシステム ビューが拡張されました。

sys.tables - 以下の 3 つの新しい列が追加されました。

o durability (0 または 1)

o durability_desc (SCHEMA_AND_DATA および SCHEMA_ONLY)

o is_memory_optimized (0 または 1)

sys.table_types - is_memory_optimized 列が追加されました。

sys.indexes - 新しい type 値 (7) および対応する type_desc 値 (NONCLUSTERED

HASH) が追加されました。非クラスター化 B ツリー インデックスと同様、範囲インデックスでは、type

値 (2) および type_desc (NONCLUSTERD) となります。

sys.index_columns 列 is_descending_key に対して、異なるセマンティックスを持つようにな

りました。ハッシュ インデックスの場合、値は意味を持たず、無視されます。

sys.data_spaces - type 列の新しい値 (7) および対応する type_desc 列の新しい値

(MEMORY_OPTIMIZED_DATA_FILEGROUP) が追加されました。

sys.sql_modules および sys.all_sql_modules - uses_native_compilation 列が追加

されました。

さらに、特にメモリ最適化テーブルに関する情報を提供するメタデータ オブジェクトが追加されました。

ハッシュ インデックスをサポートするための新しいカタログ ビュー sys.hash_indexes が追加されました。 この

ビューは sys.indexes に基づいていて、同じ列が含まれていることに加えて、列が追加されています。

bucket_count 列はインデックスに指定されたハッシュ バケットの数を示します。この値を変更するには、イン

デックスを削除または再作成する必要があります。

Page 53: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

53

動的管理オブジェクト

次に示す SQL Server 動的管理ビューは、インメモリ OLTP で新しく使用されます (xtp 識別子は

“eXtreme transaction processing” を表します)。sys.dm_db_xtp_* で始まるビューは、インメモリ

OLTP を使用できるそれぞれのデータベースに関する情報を提供し、sys.dm_xtp_* で始まるビューは、イン

スタンス全体の情報を提供します。これらのオブジェクトの詳細については、該当するドキュメントを参照してくだ

さい。これらの DMV のいくつかについては、このホワイト ペーパーの関連するセクションを参照してください。

メモリ最適化テーブルをサポートする DMV の詳細については、「メモリ最適化ビューの動的管理テーブル

(Transact-SQL)」を参照してください。

sys.dm_db_xtp_checkpoint sys.dm_db_xtp_checkpoint_files sys.dm_db_xtp_gc_cycles_stats sys.dm_xtp_gc_stats sys.dm_xtp_system_memory_consumers sys.dm_xtp_threads sys.dm_xtp_transaction_stats sys.dm_db_xtp_index_stats sys.dm_db_xtp_memory_consumers sys.dm_db_xtp_object_stats sys.dm_db_xtp_transactions sys.dm_db_xtp_table_memory_stats

xEvents

インメモリ OLTP エンジンは、監視およびトラブルシューティングに役立つ xEvents を提供します。以下のクエリ

を実行して、現在利用可能な xEvents を確認できます。

SELECT p.name, o.name, o.description

FROM sys.dm_xe_objects o JOIN sys.dm_xe_packages p

ON o.package_guid=p.guid

WHERE p.name = 'XtpEngine';

GO

パフォーマンス カウンター

インメモリ OLTP エンジンは、監視およびトラブルシューティングに役立つパフォーマンス カウンターを提供します。

以下のクエリを実行して、現在利用可能なパフォーマンス カウンターを確認できます。

SELECT object_name, counter_name

FROM sys.dm_os_performance_counters

WHERE object_name LIKE ‘XTP%’;

GO

Page 54: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

54

メモリ使用量レポート

メモリ最適化テーブルとそのインデックスによって現在使用されているメモリのインスタント レポートを取得するには、

SQL Server Management Studio から利用できるレポートを実行できます。オブジェクト エクスプローラー

で、メモリ最適化テーブルを含むデータベースの名前を右クリックし、[Reports](レポート)、[Standard

Reports](標準レポート)、[Memory Usage By Memory Optimized Objects](メモリ最適化オブジェ

クトによるメモリ使用量) の順に選択します。図 17 のようなレポートが表示されます。

図 17: メモリ最適化オブジェクトによるメモリ使用量のレポート

このレポートは、テーブル行およびインデックスによって使用される容量に加えて、システムによって使用される少

量の容量を示しています。ハッシュ インデックスでは作成されるとすぐに宣言されているバケット数に対するメモリ

が割り当てられるため、このレポートには、行が挿入される前のインデックスのメモリ使用量が示されます。範囲イ

ンデックスの場合、メモリは行が追加されるまで割り当てられないので、メモリ要件はインデックス キーのサイズお

よび行数によって異なります。

メモリ要件

インメモリ OLTP を実行するとき、すべてのメモリ最適化テーブルを保持するために、SQL Server は十分なメ

モリで構成されている必要があります。十分なメモリが割り当てられていない場合、追加のメモリを必要とする操

Page 55: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

55

作においてトランザクションは実行時に失敗します。通常、これは INSERT および UPDATE 操作中に発生

しますが、範囲インデックスを含むメモリ最適化テーブルでは DELETE 操作中にも発生することがあります。Bw

ツリーに関するセクションで説明したように、DELETE によってページのマージが発生することがあります。インデッ

クス ページは更新されないので、マージ操作は新しいページを割り当てます。インメモリ OLTP メモリ マネー

ジャーは SQL Server メモリ マネージャーと完全に統合されていて、古い行バージョンをより積極的にクリーン

アップすることによって、可能な場合はメモリ負荷に対応することができます。

メモリ最適化テーブルに必要なメモリ容量を予測するとき、大まかな目安として、データが占有するメモリ容量の

2 倍が必要になります。これを超える総メモリ要件は、ワークロードによって異なります。OLTP 操作によるデータ

変更が多数ある場合は、行バージョンに対してより多くのメモリが必要になります。既存のデータの読み取りを多

く行う場合は、必要なメモリは少なくなる可能性があります。

インデックスの容量要件を計画する場合、ハッシュ インデックスは簡単です。各バケットは 8 バイトを必要とする

ので、バケット数を 8 バイトで乗算することによって計算できます。範囲インデックスのサイズは、インデックス キー

のサイズとテーブル内の行数の両方に応じて異なります。各インデックス行が 8 バイトとインデックス キーのサイズ

(K バイト) と仮定できるため、1 ページに収まる最大行数は 8176/(K+8) となります。その結果を予定され

る行数へと分割すると、初期の見積もりが得られます。すべてのインデックス ページが 8 バイトであるわけではな

く、すべてのページが必ずしも完全にフルであるわけではありません。ページを分割およびマージする必要があると

き、新しいページが作成されます。ガベージ コレクション処理が削除するまで、それらのページのための容量を確

保する必要があります。

リソース ガバナーによるメモリの管理

メモリをプロアクティブに管理できるツールが SQL Server リソース ガバナーです。CTP2 以降、データベースを

リソース プールにバインドし、このプールに一定のメモリ容量を割り当てることができます。そのデータベース内のメ

モリ最適化テーブルは、それを超えるメモリを使用できません。メモリ負荷下でシステムが安定性を維持するため

に、割り当てることができる容量については、80% というハード制限が設けられています。実際、メモリ最適化

テーブルとそのインデックスによって使用されるメモリは、リソース ガバナーによって管理されます。他のクラスのメモ

リはリソース ガバナーによって管理されません。データベースがプールに明示的にマップされていない場合は、暗示

的に既定のプールにマップされます。

SQL Server リソース ガバナーの詳細については、SQL Server 2008 のリリース時に公開されたリソース ガ

バナーに関する詳しいホワイト ペーパーを参照してください。

http://view.officeapps.live.com/op/view.aspx?src=http%3A%2F%2Fdownload.microso

ft.com%2Fdownload%2FD%2FB%2FD%2FDBDE7972-1EB9-470A-BA18-

58849DB3EB3B%2FResourceGov.docx

Page 56: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

56

SQL Server 2012 でのリソース ガバナーの変更点については、以下を参照してください。

http://msdn.microsoft.com/ja-jp/library/jj573256.aspx

最初の手順は、MAX_MEMORY_PERCENT 値を指定して、インメモリ OLTP データベース用のメモリ プー

ルを作成することです。これはこのプールと関連付けられたデータベース内のメモリ最適化テーブルに割り当てるこ

とができる SQL Server メモリの割合を指定します。

例:

CREATE RESOURCE POOL HkPool WITH (MAX_MEMORY_PERCENT=50);

ALTER RESOURCE GOVERNOR RECONFIGURE;

リソース プールを作成した後、プロシージャ sp_xtp_bind_db_resource_pool を使用して、管理するデー

タベースを各プールにバインドする必要があります。1 つのプールに複数のデータベースを含めることができますが、

データベースは任意の時点で 1 つのプールとのみ関連付けられます。

以下に例を示します。

EXEC sp_xtp_bind_db_resource_pool 'HkDB', 'HkPool';

メモリは割り当て時にリソース プールに割り当てられるので、データベースをプールと関連付けるだけでは既に割り

当てられているメモリの割り当ては移動しません。これを行うには、データベースをオフラインにし、再びオンラインに

戻す必要があります。データがメモリ最適化テーブルへと読み込まれるときに、メモリは新しいプールと関連付けら

れます。

例:

ALTER DATABASE [HkDb] SET OFFLINE;

ALTER DATABASE [HkDb] SET ONLINE;

データベースとプールの間のバインドを削除する場合は、プロシージャ

sp_xtp_unbind_db_resource_pool を使用できます。たとえば、データベースを異なるプールに移動する

ことや、プールを完全に削除することに加えて、プールを他のプール (複数可) に置き換えることができます。

EXEC sp_xtp_unbind_db_resource_pool 'HkPool';

Page 57: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

57

AMR の使用

SQL Server 2014 をインストールした後は (管理ツールの完全なセットをインストールするように選択している限

り)、AMR (Analysis, Migration and Report) ツールを使用すると、インメモリ OLTP に移行する対象として推奨

されるテーブルやプロシージャについて知ることができます。

AMR は、管理データ ウェアハウス (MDW) を使用し、データ コレクター、MDW データベース上で右クリックし

て、[Reports](レポート) から [Management Data Warehouse](管理データ ウェアハウス) を選択す

ると表示されるプロシージャ レポートを使用します。レポートが表示された後、[Transaction Performance

Analysis Overview] (トランザクション パフォーマンス分析の概要) オプションを利用できます。

レポートの 1 つには、メモリ最適化テーブルに変換された場合に最大のパフォーマンスを得られるテーブルに関す

る推奨情報が含まれています。このレポートには、そのテーブルで現在使用されていてサポートされていない機能

の数に基づいて、テーブルの変換に必要となる作業についても示されます。たとえば、現在のテーブルで使用され

ていて、メモリ最適化テーブルではサポートされていないデータ型や制限が指摘されます。

別のレポートでは、メモリ最適化テーブルを使用する際にネイティブにコンパイルされたプロシージャに変換すること

でメリットが生じるプロシージャに関する推奨情報が示されます。

メモリ最適化テーブルは変換された Transact-SQL だけでなくネイティブにコンパイルされたストアド プロシー

ジャでもアクセスできるという事実、そしてメモリ最適化テーブルはディスク ベース テーブルと同じクエリで使用でき

るという事実は、インメモリ OLTP 環境への移行を段階的かつ反復的に実行できることを意味します。管理

データ ウェアハウス (MDW) のレポートに示された推奨情報を利用すれば、メモリ最適化構造の利点を最大

限に活用できるものから順に、テーブルを一度に 1 つずつメモリ最適化テーブルに変換することができます。メモ

リ最適化テーブルへの変換の利点が明確になるにつれて、変換するテーブルの数を増やしながら、通常の

Transact-SQL インターフェイスを使用してそれらのテーブルにアクセスできるので、アプリケーションの変更はほ

とんど必要がありません。

テーブルの変換が完了すれば、管理データ ウェアハウスのレポートで最大の利点があると示されているものから

順に、ネイティブにコンパイルされたストアド プロシージャへのコードの書き換えを検討することができます。

まとめ

SQL Server のインメモリ OLTP を使用すると、メモリ最適化と効率的な管理が可能なテーブルを作成および

処理することが可能になり、OLTP のワークロードのパフォーマンスを最適化することができます。このようなテーブ

ルは真のマルチバージョン オプティミスティック同時実行制御によってアクセスされるため、処理中にロックもラッチ

Page 58: SQL Server 2014 CTP2 インメモリ OLTP 機能の概要download.microsoft.com/download/9/8/0/980B9E8B...えから生まれています。cep (複合イベント処理)、データ

58

も発生しません。すべてのインメモリ OLTP のメモリには、少なくともインデックスが 1 つ必要で、すべてのアクセス

はインデックスを通して実行されます。インメモリ OLTP のメモリは、ごくわずかな制限があることを除き、ディスク

ベース テーブルと同じトランザクションで参照することが可能です。ネイティブにコンパイルされたストアド プロシー

ジャは、メモリ最適化テーブルおよびパフォーマンス ビジネス ロジック計算にアクセスするための最速の方法です。

詳細情報

http://www.microsoft.com/ja-jp/sqlserver/: SQL Server Web サイト

http://technet.microsoft.com/ja-jp/sqlserver/: SQL Server TechCenter

http://msdn.microsoft.com/ja-jp/sqlserver/: SQL Server 開発者向け技術情報

このホワイト ペーパーはお役に立ちましたか。フィードバックをお寄せください。1 (まったく役に立たなかった) ~ 5

(非常に役に立った) の数字でお答えください。このホワイト ペーパーをどのように評価しますか。また、なぜそのよ

うに評価しましたか。例:

高い評価は、適切な例、良好なスクリーン ショット、明確な説明、または別の理由によるものですか。

低い評価は、不適切な例、不鮮明なスクリーン ショット、または不明確な説明によるものですか。

このフィードバックは、リリースされるホワイト ペーパーの品質改善に役立ちます。

このホワイト ペーパーは、最終製品リリースの際にインメモリ OLTP に関する書籍になる予定です。書籍には、

以下のトピックに関する技術的な詳細が記載される予定です。

1. 監視とトラブルシューティング

2. データ検証

3. ベスト プラクティスの提案

これらの領域において質問がある場合、または現在のホワイトペーパーに記載されている領域で、書籍で取り上

げてほしい領域がある場合は、フィードバック リンクを通じてお送りください。

フィードバックを送る