Oracle字符串搜索性能问题

时间:2012-08-29 20:49:30

标签: oracle performance indexing hint

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

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

如果我只搜索波士顿这样的单词,如“boston%”,则只需0.15秒。

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

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

select description /*+ index name_idx */  from travel_websites where name like "%boston%";

任何建议都将不胜感激。

2 个答案:

答案 0 :(得分:5)

您不能对具有前导通配符(即like '%boston%')的谓词使用索引范围扫描。如果您考虑索引如何存储在磁盘上,这是有道理的 - 如果您不知道要搜索的字符串的第一个字符是什么,则无法遍历索引以查找与该字符串匹配的索引条目。您可以对读取每个叶块的索引进行全面扫描,并在那里搜索name以查看它是否包含您想要的字符串。但是,这需要对索引进行全面扫描,然后您必须访问从索引获取的每个ROWID的表,以便获取不属于您刚刚完全扫描的索引的任何列。根据表的相对大小和索引以及谓词的选择性,如果您正在搜索前导通配符,优化器可以轻松地决定只执行表扫描。

Oracle does support full text search但您必须使用Oracle Text,这需要您在name列上构建Oracle Text索引并使用CONTAINS operator进行搜索而不是使用{ {1}}查询。 Oracle Text是非常强大的产品,因此在构建索引,刷新索引和构建查询时,有很多选项可供考虑,具体取决于您希望获得的复杂程度。

未正确指定索引提示。假设LIKE上有索引,该索引的名称为name,并且您要强制完全扫描索引(只是重申,索引上的范围扫描不是一个有效的选项,如果有一个前导通配符),你需要像

这样的东西
name_idx

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

答案 1 :(得分:2)

Oracle(据我所知大多数其他数据库)默认索引字符串,以便索引只能用于从字符串的开头查找字符串匹配项。这意味着,LIKE 'boston%'(startswith)将能够使用索引,而LIKE '%boston'(endswith)或LIKE '%boston%'(包含)则不会。

如果您确实需要能够快速查找子字符串的索引,则不能对字符串使用常规索引类型,但可以使用TEXT索引,这可能需要稍微不同的查询语法。