最近、いくつかのパフォーマンステストを行っているときに、このことに気付きました。暗黙的な変換が必要な列に値を挿入すると(たとえば、bigint
からnvarchar
に)、警告が表示されます。
式での型変換
(CONVERT_IMPLICIT(nvarchar(50),[tempdb].[dbo].[#MyFunIntTable].[EvenCoolerColumn],0))
は、クエリプランの選択で「カーディナリティの見積もり」に影響する場合があります。
私は関係者であるため、明らかな容疑者をすべてチェックし、最終的にXMLを調べて、テーブルへの挿入について実際に警告が出されていることを確認しました。問題は、なぜこれがカーディナリティの推定に影響を与えるのか理解できないことです。結合または少しロジックが多い場所でこれを実行している場合は理にかなっていますが、実際の挿入操作でカーディナリティの見積もりの不一致はないはずですよね?
これは、単純なクエリではなく、複数の値が挿入されるか、テーブルから値をプルするとすぐに発生することに気づきました。
この質問は、次のような潜在的な重複を引き起こしています。
私は文字通りこのコラムで何もしていないので、これらの質問とは異なると思います。フィルター、並べ替え、グループ化、結合、または関数で使用していません。これらのいずれかにより、シナリオがより複雑になります。私がしているのは、bigint
をnvarchar
に挿入することだけです。これは、私が考えることができる意味のあるカーディナリティの推定に影響を与えることはありません。
私が答えから特に探しているのは:
以下の簡単な例で再作成しました( 計画を貼り付けます )
DROP TABLE IF EXISTS #MyFunStringTable;
DROP TABLE IF EXISTS #MyFunIntTable;
CREATE TABLE #MyFunStringTable
(
SuperCoolColumn nvarchar(50) COLLATE DATABASE_DEFAULT NULL
);
CREATE TABLE #MyFunIntTable
(
EvenCoolerColumn bigint NULL
);
INSERT INTO #MyFunIntTable
( EvenCoolerColumn )
VALUES
( 1 ),
( 2 ),
( 3 ),
( 4 ),
( 5 );
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
SELECT EvenCoolerColumn
FROM #MyFunIntTable;
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
VALUES
( 1 );
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
VALUES
( 1 ),
( 2 );
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
SELECT 1;
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
SELECT 1
UNION ALL
SELECT 2;
INSERT INTO #MyFunStringTable
( SuperCoolColumn )
SELECT 1
FROM #MyFunIntTable;
他の実行プランの警告と同様に、これは情報を提供するものです。クエリの実行速度が遅い場合、またはカーディナリティの推定値が正しくないことに気付いた場合、警告により、考えられる原因を探す場所に関する情報が提供されます。
純粋に実用的な問題として、これでほぼ終わりです。このオプティマイザ警告をトリガーする正確な条件は文書化されていません。
とはいえ、あなたの好奇心を少し満たすために、少し詳しく説明します。
1.何も行われていないにもかかわらずこの警告が表示される理由の説明-SQL Serverが計画の選択に影響を与えない場合でも、保守的でレポートが作成されるだけですか?
クエリオプティマイザのカーディナリティ推定コンポーネントに関心があるあります。このコンポーネントは、クエリツリー内の各論理演算子のさまざまなプロパティやその他の情報を追跡します。これには、ヒストグラム(ディスクから、または完全にメモリ内から導出)、ドメイン情報、機能の依存関係などが含まれます。
特定の例では、変換への入力が monotone であることがわかっているが、出力がそうでない場合に警告がトリガーされます。 integer
リテラルからbigint
への変換では、このプロパティが保持されます。 bigint
からnvarchar(50)
への変換は行いません。
単一のリテラル整数定数がある場合、最適化が開始する前に、解析時の定数の折りたたみによってこれがnvarchar
に変換されます。これにより、プランでの型変換および関連する警告が回避されます。
元のカーディナリティエスティメータと新しいカーディナリティエスティメータの間には、詳細な内部実装の違いがあります。つまり、一部のステートメントでは、一方のCEでのみ警告が生成され、もう一方では警告が生成されません。
2.ここで実際にどのカーディナリティ推定が危険にさらされているか、およびそのカーディナリティ推定の不正確さに基づいてどの操作が変更されるか?
例のステートメントでは、なし。前述のように、変換は他の内部データに影響を与える可能性があります。他のプラン演算子、またはオプティマイザを通過するコードパス。広い点は、考慮すべき生のカーディナリティの見積もり以上のものがあるということです。内部的な違いは、インデックス付きビューや計算された列のマッチングなどに影響を与える可能性があります。
3.これがプランの選択に影響を与える可能性のあるシナリオはありますか?明らかに、変換された列で結合またはフィルタリングを開始した場合は可能ですが、現状のままですか?
これは前の質問と同じようです。
4.データタイプを変更する以外に、警告を防ぐためにできることはありますか(これはデータモデルの相互作用の要件であると想定しています)
これらの警告をオフにするオプションはありません。