5 に答える
LIKE の代わりにフルテキスト インデックスを使用します。
フルテキスト インデックスを作成します。
http://msdn.microsoft.com/en-us/library/ms187317.aspx
CREATE UNIQUE INDEX ix1 ON tbl_MyTable(YourKey); //unique index required
CREATE FULLTEXT CATALOG ft AS DEFAULT; // ft is your freetext catalog name
CREATE FULLTEXT INDEX ON tbl_MyTable(Name)
KEY INDEX ix1
WITH STOPLIST = SYSTEM; // this is your index and allows you to run the command below
次に、これを使用してクエリを実行します。
SELECT Name
FROM tbl_MyTable
WHERE FREETEXT(Name, 'dont');
それがこの種の最速のテクニックです。サードパーティのフリーテキスト エンジンを使用するとさらに高速化できますが、おそらくその必要はありません。
以下を試して、引用符や二重引用符なしですべての名前を返します。これにより、LIKE ステートメントが不要になり、別の列が不要になり、クエリが高速化されます。
SELECT Replace(
Replace(
Replace(
Replace(
Replace(
Replace( Name, '“', ''),
'‘', ''),
'''',''),
'"', ''),
'’',''),
'”', '') AS Name
FROM tbl_MyTable
これは質問への回答ではありませんが、コメントとして実装するのは非常に困難です。
UDF を使用してクエリ自体を簡素化する場合は、関数呼び出しを 2 倍ではなく、使用している行数に制限してください。それ以外の:
where dbo.udf_StripQuotes(name) like 'dont%'
or dbo.udf_StripQuotes(name) like '% dont%' );
これを行う:
where ' ' + dbo.udf_StripQuotes(name) like '% dont%';
根本的な問題に関しては、インデックス付きの計算列が最適かもしれないという Michael の意見に同意しますが、name 列が 900 バイトを超える場合、これは不可能です (これにより、魔法のようにスキャンがシークに変わることはありません。ワイルドカードを使用すると、関数を呼び出したり、クエリですべての置換呼び出しを実行したりする必要がなくなります)。
空間的に効率的か、時間的に効率的か?
最初のソリューションはスペース効率が良いですが、クエリが実行されるたびに複数の文字列関数をテーブルの各行に適用するため、時間効率が悪い可能性があります。
生成された列の解決策はスペース効率が悪いですが、文字列操作を 1 回 (列を追加してから挿入/更新時に) 適用するため、時間効率が高い可能性があります。
ユーザーの観点からすると、最適なソリューションは、生成された列で実行される検索である可能性があります。
このロジックを統合するために、ユーザー定義関数を作成することをお勧めします。
CREATE FUNCTION [dbo].[udf_StripQuotes]
(
@String VARCHAR(MAX)
)
RETURNS VARCHAR(MAX)
AS
BEGIN
RETURN Replace(
Replace(
Replace(
Replace(
Replace(
Replace(@String,'“',''),
'‘',''),
'''',''),
'"',''),
'’',''),
'”','')
END
GO
次に、次のようになります。
select Name
from tbl_MyTable
where dbo.udf_StripQuotes(name) like '% dont%';
%
効率に関して言えば、ステートメントの先頭と末尾like
が原因でインデックスを使用できなくなり、テーブル全体のスキャンが発生します...これはおそらく、このクエリの最大のパフォーマンス ヒットです。
ただし、Aaron が明らかにしたように、この実装は、UDF の呼び出しのオーバーヘッドにより、元の実装よりも遅くなります。
先頭のワイルドカードを避けることができれば、インデックス付きの計算列によってパフォーマンスが向上する可能性があります。
それ以外の場合、他の唯一のオプションはFull-Text Searchを実装することだと思います。