制限
この不正なカーディナリティ検出のしくみを使用する場合には、以下のような制限ありますので、使用の際には注意が必要です。
1. ノイズ (False positive ケース)
クエリが効率よく動作していてもイベントが発生してしまう可能性があります。たとえば、見積もり行数が1行だった場合、2行しか処理していない場合でもイベントが発生するしくみになっているので、このような現象が発生します。
2. パフォーマンスへの影響
このしくみを使用する場合、内部的にstatistics profileがオンになります。そのため、statistics profileをオンにしているときと同様のパフォーマンス インパクトが発生します。
3. 過剰見積もりは検知されない
オプティマイザが過剰見積もりを行ってしまったケースについては検知できません。例えば、1000行と見積もったけれども、実際は1行だったような場合です。しかし、通常は過剰見積もりよりも、過少見積もりのケースのほうがパフォーマンスへの影響度が高いことが多く、過剰見積もりはあまり問題となりません。実際に私が過去にトラブル シューティングでオプティマイザを何度かデバッグしたときも、オプティマイザが過少見積もりをおこなってしまい、クエリがまったく終了しないというケースでしたので、この制限についてはあまり意識しておく必要はないかもしれません。
4. 並列クエリのプラン
並列クエリの場合は、よりノイズ (False positive ケース) が発生しやすくなります。並列クエリの見積もりは、見積もり行数を単純に並列数で均等に割った値となりますが、実際に各スレッドが処理する行数は、データの配置状況などによって必ずしも均等に処理されるとは限らないからです。
このようにいくつかの制限はありますが、制限を理解したうえで使用する分にはとても便利な機能です。また、このような制限も工夫次第である程度緩和させることができます。例えば、拡張イベントでは述語によるフィルタリングが可能となっていますので、この機能を使えばある程度ノイズをフィルタリングすることも可能でしょう。
使用例
このしくみを使用して情報を採取するには、拡張イベント セッションを作成します。以下のT-SQLを実行することでinaccurate_cardinality_estimateイベントを採取することができますので、ぜひ試してみてください。なお、下記の例では、sqlserver.sql_textアクションしか設定していませんので、実際のケースでは必要に応じてさまざまな情報をあわせて採取するとよいでしょう。
CREATE EVENT SESSION [BAD CE] ON SERVER ADD EVENT sqlserver.inaccurate_cardinality_estimate( ACTION(sqlserver.sql_text)) ADD TARGET package0.event_file(SET filename=N'c:\temp\bad_CE.xel') WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS, MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE, TRACK_CAUSALITY=OFF,STARTUP_STATE=OFF) GO ALTER EVENT SESSION [BAD CE] ON SERVER STATE=START
***
いかがだったでしょうか? 私は、カーディナリティの見積もり不正に関する機能がお気に入りです。SQL Serverに限らずとも、コストベースのオプティマイザを実装しているRDBMSで、見積もりと実際の行数が乖離してしまう現象に遭遇したかたは結構いらっしゃるのではないでしょうか?あまり派手な機能ではないけれども、うれしい機能だなぁと思います。ぜひ、みなさんも試してみてください。