先行するワイルドカード (つまり ) を持つ述語に対してインデックス範囲スキャンを使用することはできませんlike '%boston%'
。インデックスがディスクにどのように格納されているかを考えれば、これは理にかなっています。検索している文字列の最初の文字がわからない場合、インデックスを走査してその文字列に一致するインデックス エントリを探すことはできません。 . すべてのリーフブロックを読み取るインデックスの完全なスキャンを実行し、name
そこを検索して、必要な文字列が含まれているかどうかを確認できる場合があります。ただし、それにはインデックスの完全なスキャンが必要であり、さらに毎回テーブルにアクセスする必要がありますROWID
フルスキャンしたばかりのインデックスの一部ではない列を取得するために、インデックスから取得します。テーブルとインデックスの相対的なサイズ、および述語の選択性に応じて、先頭のワイルドカードを検索している場合、オプティマイザーはテーブル スキャンを実行する方が速いと簡単に判断できます。
Oracle は全文検索をサポートしていますが、Oracle Text を使用する必要があります。これには、name
列に Oracle Text インデックスを作成し、問合せではなくCONTAINS 演算子LIKE
を使用して検索を行う必要があります。Oracle Text は非常に堅牢な製品であるため、どの程度高度なものを取得するかに応じて、索引の作成、索引の更新、および問合せの作成の両方で考慮すべきオプションが多数あります。
インデックス ヒントが正しく指定されていません。にインデックスname
があり、そのインデックスの名前が であり、インデックスname_idx
のフル スキャンを強制したいとします (繰り返しますが、先頭にワイルドカードがある場合、インデックスの範囲スキャンは有効なオプションではありません)。 、次のようなものが必要です
select /*+ index(travel_websites name_idx) */ description
from travel_websites
where name like '%boston%'
ただし、完全なインデックス スキャンが完全なテーブル スキャンよりも効率的であるという保証はありません。また、オプティマイザーが既にヒントなしでインデックス フル スキャンを選択している可能性は十分にあります (3 つのクエリのクエリ プランを指定しません)。