1


0

LTRIM(RTRIM(COALESCE(TextField、 '')))は悪いのですか?

私はいくつかのインデックスに参加する `char(50)`フィールドを持つ非常にトラフィックの多いテーブルを持っています。 この `char(50)`フィールドはNULLSを許します、そしてその場合NULL値は私の目的のために非NULL、長さゼロの文字列と同じであると考えられます。

私も先導を無視します

1つのテーブルからメインテーブルにデータをコピーするために使用されるsprocがあり、それは高性能である必要があります。 私は新しいデータを挿入する前に重複したレコードを削除する必要があり、私はhttps://stackoverflow.com/questions/714590/most-efficient-t-sql-delete-for-many-rows [このスレッドで]で説明した方法を使用しています。削除を実行します。

私のdelete文は次のようになります(単純化)。

delete masterTable
from masterTable t
    join incomingDataTable inc on
    (
        LTRIM(RTRIM(COALESCE(inc.TextField,''))) =
             LTRIM(RTRIM(COALESCE(t.TextField,'')))
    )
where LTRIM(RTRIM(COALESCE(t.TextField,''))) <> ''

LTRIM(RTRIM(…​))のような構文は良くありません。 自分のdeleteステートメントを改善することはできますか?もしそうなら、どのように?

編集:*明確にするために、 TextField`は両方のテーブルのインデックスに参加します。 * EDIT2: `TextField`は両方のテーブルで char(50) `として定義されています。 TEXT型ではありません。

6 回答


8


必要がある:

  1. 式を使用して + masterTable +`に計算列を作成します `+ LTRIM(RTRIM(COALESCE(TextField、 '')))+

    • この列にインデックスを作成して

    • この列を結合に使用してください。

テーブルの設計方法は、このクエリをインデックスフレンドリーにすることはまったく不可能です。

テーブル構造を変更できないが、「+ LEADING +」スペースの数を推定できる場合は、http://explainextended.com/2009/03/24/article-aware-title-filtering-internationalization/ [ ここに]。

ただし、この解決方法は、計算列にインデックスを作成するほど効率的ではありません。


4


あなたのJOINがインデックス全体をスキャンしなければならないので、それは悪いことです。 ] _

TEXTデータ型であることも確かですか。 最後に、Textデータ型の列に対してLTRIMまたはRTRIMを使用できないことを確認しましたか?

varcharコメントに対するcharに応答して、これを実行します。

@v varchar(50)、@ v2 char(50)を宣言します。@v = 'a'、@ v2 = 'a'を選択します。

データ長(@v)、データ長(@ v2)を選択


3


そのデータ型をVARCHAR(50)に変更することをお勧めします - 最大で10文字まで、CHAR(x)は少し高速でオーバーヘッドが少ないので意味があるかもしれません。特にこの列はインデックスでも使用されるため、50文字、これは大きなオーバーヘッドです。

これをVARCHAR(50)に変更すると、テーブルに必要なスペースがかなり大幅に削減され(データ量と50文字のうちどれだけが実際に使用されているかによります)あなたはもうこのCOALESCE、LTRIM、RTRIMのものを必要としないでしょう:-)

マーク


2


SQL Serverでは、埋め込み文字列を埋め込み文字列と一致させてLTRIM / RTRIMの手間を省くことができると思います。

ただし、データの整理はすべてETLの一部であり、データが目的の場所に到達する前に実行する必要があります。 大規模なデータセットでは、データの一時コピーを作成し、それを再処理し、それにインデックスを付けてから、必要なマッチングを行う方が早いことがあります。


2


SQLMenaceは正しいと思います。

その列に空白がないことを保証するためにテーブルに* INSERT / UPDATEトリガ*を追加するのはどうですか。

列がVARCHARの場合、SQL Serverは自動的に末尾の空白を無視します。 先頭の空白はまだ数えます。

実際、SQL ServerはJOINを実行する前に両方の列を自動的にCHAR(50)にパディングしませんか? (暗黙的な変換)


2


データを使用するたびにデータをトリミングする必要がある場合は、charデータ型ではなくvarcharデータ型にしてください。 フィールドを照会するたびに関数を使用する必要があるときはいつでも、データベース設計に問題があります。

https://stackoverflow.com/questions/758699/is-the-char-datatype-in​​-sql-obsolete-when-do-you-use-it/760511#760511[ CHARデータ型です。 SQLで時代遅れ? いつ使用しますか。