10

117000 レコード程度のテーブルがあります。特定の文字列パターンの 3 つの個別のフィールドをチェックする検索を実行する必要があります。

私の where 句は次のとおりです。

field1 LIKE '%' + @DESC + '%'
OR field2 LIKE '%' + @DESC + '%'
OR field3 LIKE '%' + @DESC + '%'

これは、入力に関係なく約24秒かかるようです...

これを行うより良い方法はありますか?10 (または 5!) 秒未満の方がはるかに望ましいでしょう。

助けてくれてありがとう。

4

7 に答える 7

13

全文検索とCONTAINSを使用します。フィールドの途中で検索する場合、LIKE は最適化できません。LIKE 式が「%」で始まる場合、常にフル テーブル スキャンが実行されます。

于 2009-10-14T21:09:05.963 に答える
2

ワイルドカードを使用して LIKE 検索を開始するときはいつでも、スキャンを実行しています。最初の文字を含めるように検索条件を絞り込めない限り (実現不可能な場合があります)、全文検索に頼る必要があります。

于 2009-10-14T21:09:49.237 に答える
1

全文索引が最善の解決策であり、実行する必要がある場合に主要なワイルドカード検索の使用を推奨しているわけではないという受け入れられた回答に同意しますが、それらのパフォーマンスを低下させるために実行できる潜在的な手順があります悪い。

「 MicrosoftSQLServer2008 Internals」という本の中で、KalenDelaneyは次のように述べています。

SQL Serverが文字列内のほぼすべての文字を調べなければならない場合、照合は大きな違いを生む可能性があります。たとえば、次を見てください。

SELECT COUNT(*) FROM tbl WHERE longcol LIKE '%abc%'

これは、非バイナリのWindows照合よりも、バイナリ照合で10倍以上高速に実行される可能性があります。また、varcharデータの場合、これはWindows照合よりもSQL照合の方が最大7倍または8倍高速に実行されます。

于 2010-09-19T02:29:43.933 に答える
1

本当にワイルドカードから始める必要がありますか? なんで?多くの場合、少なくとも最初の文字を入力するようユーザーに強制できます。一部の開発者は、要件があるためではなく、習慣としてワイルドカードを使用しているため、これを取り上げます。ほとんどの場合、フィールドに長い文字列が格納されていない限り (たとえば、公式の空港名など)、ユーザーは最初の文字を入力できます。それ以外の場合は、完全なテキスト インデックスを使用する必要がありますが、最後にワイルドカードが必要ない場合は、逆の KM のトリックが非常に優れています。

パフォーマンスを損なうようなことを避けることができる場合は、そうしてください。

于 2009-10-14T21:41:28.083 に答える
0

どうですか

field1 + field2 + field3 LIKE '%' + @DESC + '%'

また

CONTAINS(field1 + field2 + field3, @DESC)
于 2009-10-14T21:39:53.687 に答える
0

1つの可能な解決策を試しました。このソリューションの前は、クエリでも結果が返されず、接続タイムアウト エラーが発生していました。

私のクエリには、日付フィルターとその他の基準がありました。他のすべての基準は検索に似ていました。1 つの列キーワードが ntext 列で '%abc%' のように検索され、完全なテーブル スキャンを実行していました。

解決:

クエリを 2 つの部分に分割します。1) CTE (Common Table Express) の最初の部分 2) CTE のすべての検索基準を適用します。

WITH SearchData(Column1,Column2,Column3,Column4,........)
    AS
    (
    SELECT Column1,Column2,Column3,Column4,...........
    FROM myTable1 WITH(NOLOCK) 
            INNER JOIN MyTable2 WITH(NOLOCK) 
                ON MyTable1.id = MyTable2.Id
    WHERE (MyTable1.CreationTime >= '2014-04-27' AND MyTable1.CreationTime <= '2014-05-01') 
 )

    SELECT DISTINCT top 250 Column1,Column2,Column3,Column4
    FROM SearchData
    WHERE   (ISNULL(Column1,'') LIKE @Column1  +'%' OR @Column1 IS NULL)
            and (Column2 LIKE @Column2+ '%' OR @Column2 IS NULL)
            ...
            ...
            ...
            ...
            AND (Column10 like '%'+@Column10+'%' or @Column10 IS NULL)
            AND @Column1+@Column2+@Column3+........@Column10 <> ''  
            ORDER BY [CreationTime] DESC

それは私のために働いた。

于 2015-09-01T10:29:13.240 に答える