2014年にリリースされたSQL Serverのメモリ最適化テーブル(memory-optimized table)は,ロックフリーな書き込みや完全にコンパイルされたストアドプロシージャ,ディスクI/Oを回避するオプションにより,従来のテーブルに対して大きなパフォーマンス上のアドバンテージを提供する機能だ。ただし,NoSQLスタイルの設計で多用される大規模なドキュメントに対応できないなど,制限も少なくない。
SQL Server 2016では,このような制限の多くが解消されている。まず最初にあげられるのは,メモリ最適化テーブルとコンパイルされるストアドプロシージャの両方でLOB型がサポートされたことだ。これにより,varChar(max)やnBVarChar(max) (いずれもXMLとJSONデータをカバーする)やvarBinary(max)が使用可能になる。8,060バイトまでという行サイズの制限も引き上げられたので,LOB型を含まないテーブルについても,よりサイズの大きなものが可能になった。
しかしながらMicrosoftは,この機能について,可能ならば使用しないことを推奨している。varChar(max)ではなく,すべてをvarChar(8000)以下の列に収めることができれば,書き込み時に大規模オブジェクトを格納する隠しテーブルが使用されることによるデメリットを受けなくて済む,というのが理由だ。
メモリ最適化テーブルの制約
メモリ最適化テーブルにはさらに,制約(constratint)を(ユニークなプライマリキー以外に)作成できない,という制限もあった。アプリケーション設計の観点からは必須な機能ではないにせよ,制約を使うことができれば,いくつかのタイプのデータ破損の可能性を排除できる。
- メモリ最適化テーブル間のFOREIGN KEY制約
- CHECK制約
- UNIQUE制約
通常のテーブルとメモリ最適化テーブル間の外部キー制約が引き続き許可されない点には注意が必要だ。
ネイティブコンパイルされるストアドプロシージャの改善
ここで言う“コンパイルされるストアドプロシージャ”とは,作成時に高度に最適化されたマシンコードにコンパイルされるストアドプロシージャのことだ。操作対象はメモリ最適化テーブルに限定されるが,実行時に解釈される通常のストアドプロシージャに比較して,大幅なパフォーマンスの向上を得ることができる。
LOB型のサポートに加えて,INSERT, UPDATE, DELETE文でOUTPUT句の使用が可能になった。これによってクエリを別途用意する必要がなくなり,ひとつのトランザクションと,それに伴うロックの必要性を排除することができる。
その他にも,次のような標準SQL機能が使用できるようになった。
- UNIONとUNION ALL
- SELECT DISTINCT
- OUTER JOIN
- SELECT文内のサブクエリ (EXISTS、IN、スカラー副問合せ)
ネイティブコンパイルされる関数
スカラ関数のネイティブコンパイルが可能になった。これを利用するには,ディレクティブとしてWITH NATIVE_COMPILATION, SCHEMABINDINGを使用した上で,実際のコードをBEGIN ATOMICブロックで囲む必要がある。これは,WITH SCHEMABINDINGディレクティブのみでマークされた,コンパイルされるストアドプロシージャとは違うものだ。
ネイティブコンパイルされるトリガ
同じ目的で,WITH NATIVE_COMPILATIONを使うことで,AFTERトリガをメモリ最適化テーブルに配置することが可能になった。
詳細については,"What's new in SQL2016 CTP3”および"What's new for In-Memory OLTP in SQL Server 2016 since CTP3”を参照してほしい。