3

継承したコードを確認しているところ、次のような行が見つかりました。

And isnull(IH.CustomerItemNumber, '') <> ''

私の前任者のどれが、大量のwhere句またはjoin句で使用したようです。これは関数の不要な呼び出しであるように見えます。そのため、NULLが空の文字列''と等しくなることはないため、パフォーマンスが低下します。

具体的には、特定のクエリの結合句からこれを削除すると、パフォーマンスが劇的に向上しました(46〜49秒から1〜3秒)。

に置き換えましたAND IH.CustomerItemNumber <> ''

私の評価はここで正しいですか?これは冗長で低速であり、削除できますか?このコードはどのような状況で有益でしょうか?

編集:それで、NULLは空の文字列と等しくなることができますか?

4

4 に答える 4

5

これは意味的には次と同じです。

And IH.CustomerItemNumber <> '' And IH.CustomerItemNumber Is Not Null

したがって、列がnullでも空の文字列でもないことを確認しています。重要かもしれません。

アップデート

この場合、文字列リテラル(空の文字列)の不等式を探しているため、少なくとも3つの意味的に正しいオプションがあります。

  • And IH.CustomerItemNumber <> ''
  • And IH.CustomerItemNumber <> '' And IH.CustomerItemNumber Is Not Null
  • And isnull(IH.CustomerItemNumber, '') <> ''

1つ目は、 ansi_nulls設定<> ''に関係なく、nullと一致しないため、他の2つと同じ結果セットを返します。

開発システムでの簡単なテストでは、最初と2番目の両方がインデックスシークを利用しました。最初のテストは、いくつかの非常に単純化されたテストの1つで、2番目のテストをわずかに上回っています。

3つ目は、関数呼び出しを追加するため、他のインデックスのようにインデックスを使用しない可能性があるため、これはおそらく最悪の選択です。とはいえ、簡単なテストでは、isnullはインデックススキャンを使用できました。3番目の選択肢にさらに追加Is Not Nullすると、実際に速度が上がり、インデックスシークに移動しました。図に移動します(GO!GO!クエリオプティマイザ!)。

@Gordonと同様に、2番目のオプションもほとんどの場合選択します。これは、他の開発者(または自分自身)に対して自分の意図をより適切に示し、nullになる可能性のある別の列に対して同等性をチェックする場合に従う方がよいためです(考えてみてください)。潜在的なansi_nullsのオフ)。

完全を期すために:

  • And nullif(IH.CustomerItemNumber, '') is not null
  • And case when IH.CustomerItemNumber = '' then null else IH.CustomerItemNumber end is not null
  • And case IH.CustomerItemNumber when '' then null else IH.CustomerItemNumber end is not null

SQL Serverではすべて(私が知る限り)まったく同じように解釈され、上記の3番目のオプションと同じように実行されます。

于 2012-10-25T18:22:15.790 に答える
4

コードが存在する理由は、アプリケーションの履歴が原因である可能性があります。おそらくある時点で、フィールドでNULLが許可されていました。次に、これらは空の文字列に置き換えられました。

コードが非効率的である理由は、結合の最適化のためです。 ISNULL()また、同等のANSI規格でCOALESCE()は、通常、クエリの処理にかかるオーバーヘッドはごくわずかです。(SQl Serverの一部のバージョンではCOALESCE()、最初の引数を2回評価するようです。これは、サブクエリの場合に問題になります。)

私の推測では、フィールドにはインデックスがあります。SQL Serverは、フィールドが単独で使用される場合、結合にインデックスを使用することを認識しています。関数呼び出しに含まれるときにインデックスを使用するのは賢くありません。クエリの速度を低下させているのは結合の最適化であり、関数呼び出しのオーバーヘッドではありません。

個人的には、パフォーマンスが同じである場合は、明示的なNULLチェックを使用したフォームをお勧めします。

IH.CustomerItemNumber <> '' and IH.CustomerItemNumber is not null

NULL処理について明示的にすることは、将来的にコードを維持するのに役立つだけです。

于 2012-10-25T18:32:51.903 に答える
1

NULLチェックに使用できます。

And (IH.CustomerItemNumber IS NOT NULL) AND (IH.CustomerItemNumber <> '')

ところで、 ISNULL(check_expression、replacement_value)-NULLを指定された置換値に置き換えます。

あなたの場合、IH.CustomerItemNumberの値がnullの場合、それは空の値に置き換えられ、空の文字列と比較されます。

于 2012-10-25T18:22:04.510 に答える
0

NULLが空の文字列''と等しくなることは決してないからですよね?

NULLは、空の文字列と等しくなることもありません...一度に両方であり、同時にすべてではありません。それはあなたが確かに知らない状態を伝えます。

于 2012-10-25T18:40:07.190 に答える