SQL Server 2017 では、Adaptive Query Processing というクエリ実行の最適化が導入されました。
クエリを再コンパイルすことなく、一部の実行プランの操作を処理対象のデータに適応した形で実行する処理であり、互換性レベル 140 に設定することで、適用される機能となっています。

上記の画像は、ドキュメントから取得したものなのですが、適応対象となる処理は一部のもので、「バッチモード」が対象となっていました。
SQL Server 2017 では、バッチモードで実行されるのは、「列ストアインデックス」が使用される場合となっており、Adaptive Query Processing が適用されるのは、かなり限定的なものとなっていました。
初出は PASS Summit だとおもいますが、これの一歩進んだものが、SQL Database では「Intelligent Query Processing」として、プレビュー機能として提供が行われている、次代の互換性レベルである、互換性レベル「150」で使用することができるようになっています。
Intteligent Query Processin は Adaptive Query Processing を発展させたものであり、従来からの Adaptive Query Processing に加えて、対象が次のように増加しています。
![]()
新たに実装されたのは次の 3 種類となります。
- Approximate Count Distinc
- Row Mode Memory Grant Feedback
- Table Variable Deferred Compilation
7 月の段階で細かな情報が公開されていますが、簡単に動作をまとめて置こうかと。
Approximate Count Distinct
重複を除いた件数の取得を概算でも構わないという場合に、高速でデータの取得が行える機能となります。
少量のデータでは、通常の COUNT(DISTINCT()) とあまり速度差はない可能性がありますが、データ量が多ければ多いほど、効果が表れるといったものとなります。
一般的には、 2% 程度の誤差と言われており、最大でも 20% 程度の誤差を目標とした精度となるような形での実装で考えられているものです。
実際には次のようなクエリの実行となります。
SELECT FORMAT(COUNT(DISTINCT L_ORDERKEY), '#,0') FROM LINEITEM SELECT FORMAT(APPROX_COUNT_DISTINCT (L_ORDERKEY), '#,0') FROM LINEITEM
上が COUNT の結果、下が、APPROX_COUNT_DISTINCT (Approximate Count Distinct) の結果となります。
![]()
Approximate Count Distinct は概算のため、通常の COUNT(DISTINCT) を実行した場合と比較して、データの件数に差が出ていますね。
実行プランの比較がこちらになります。
今回、全体で、600 万件程度のデータ件数の環境で実行していますが Approximate Count Distinct の方がコストが低くなっていますね。
![]()
実行プランについても変化していますね。
実装については、他の DB の APPROXIMATE と似ている感じなのではないでしょうか。
Row Mode Memory Grant Feedback
これは、SQL Server 2017 で実装された Batch Mode Memory Grant Feedback の拡張版で、Memory Grant Feedback が列ストアインデックスの設定されていない、行ストアのテーブルでも使用できるようになりました。
互換性レベル 140 の場合、Memory Grant Feedback は列ストアが対象となりますので、動作は行われません。
![]()
互換性レベル 150 の場合は、行モードで Memory Grant Feedback が実行できるようになり、ワークスペースメモリの許可の情報に Memory Grant Feedback の内容が追加されています。
![]()
これにより、処理対象の件数に応じて、ワークスペースのメモリ確保が動的に調整されるようになりますので、初回コンパイル時の処理対象件数により性能劣化への影響を抑えることができるようになります。
Table Variable Deferred Compilation
SQL Server 2017 では、複数ステートメントのテーブル値関数のインターリーブ実行が可能となりましたが、互換性レベル 150 では、テーブル変数の遅延コンパイルが有効になり、テーブル変数を使用したクエリでより最適な実行プランを選択できるようになります。
互換性レベル 140 の場合、テーブル値変数からデータを取得した際の予測行数が 1 行となっています。
![]()
互換性レベル 150 を使用した場合、予測行数がテーブル変数に設定したデータ件数により即したものとなります。
予測値の正確性が増すことで、並列クエリの実行にもつながっていますね。
![]()
冒頭で書いたように、Intelligent Query Processing の初出は、PASS Summit の https://github.com/joesackmsft/Conferences/blob/master/PASSSummit2017/Intelligent-QP.pdf のセッションでした。
この中で発表されたものの中で、まだ実装されていないものがいくつかありそうなので、今後も情報をウォッチする必要がありますが、実行タイミングの処理件数に適した、クエリの自動的な最適化は今後も進んでいきそうですね。