Oracle字符串搜索性能问题

dav*_*ave 1 oracle indexing performance hint

我在Oracle 11GR2中有一个简单的搜索存储过程,在一个包含超过160万条记录的表中.我很困惑的事实是,如果我想在列中搜索一个工作,例如"%boston%",则需要12秒.我有一个名称collumn的索引.

select description from travel_websites where name like "%boston%";
Run Code Online (Sandbox Code Playgroud)

如果我只搜索波士顿这样的单词,比如"boston%",那只需要0.15秒.

select description from travel_websites where name like "boston%";

我添加了一个索引提示并尝试强制优化器在名称列上使用我的索引,它也没有帮助.

select description /*+ index name_idx */  from travel_websites where name like "%boston%";
Run Code Online (Sandbox Code Playgroud)

任何建议将不胜感激.

Jus*_*ave 6

您不能对具有前导通配符(即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%'
Run Code Online (Sandbox Code Playgroud)

但是,无法保证完整索引扫描比全表扫描更有效.并且完全有可能优化器在没有提示的情况下选择索引全扫描(您没有为三个查询指定查询计划).