web-dev-qa-db-ja.com

クラスター化インデックスシークは、基になるテーブルの行よりも「実際の行数」が多いのはなぜですか?

SQL Server(技術的にはAzure SQL Database)に関連する問題のトラブルシューティングを行っています。統計情報が歪んでいるために、不適切な実行プランが時々選択されています。 sp_updatestatsは毎回それを修正し、数時間後または数日後に不良プランが再度キャッシュされるまで。

「悪い」計画を見て、奇妙なことに気づいたことがあります。現在約170万行あるテーブルにクラスター化インデックスシークがあります。この操作の「推定行数」は約1200で、この場合、その操作から予想される平均行数と間違いなく一致していますが、「実際の行数」は6000万を超えています。このリーフノードの太い線に続いて、結合や並べ替えなどのさまざまなダウンストリーム操作が6千万件すべてで実行されており、過度の速度低下、tempdbへの流出、その他の問題を引き起こしています。

Clustered Index Seekが実際に何をしているのかを誤解しているはずです。これは、基になるテーブルよりも多くの行を "出力"することは不可能だと思うからです。何が原因でしょうか?さらに良いことに、それを修正する方法についての指針はありますか?

[「sp_updatestats」のようなものを含めると、毎回修正されますが、永続的に修正する方法がわからない場合は、この記事を読んでください。」これは最近、いくつかの異なる分野で私たちにとって一般的な問題となっています。]

6
Todd Menier

ネストされたループの内側(下側)にあるため、Seekはより多くの行を返します。外部操作によって返されるすべての行は、新しいSeek操作になります。したがって、1つのSeekから60mの行を取得するのではなく、9000以上の行(実行数)を取得します。

注:見積もりを見ると、見積もり行の総数は見積もり実行数見積もり行数を掛けたものになります。

6
Forrest