【问题标题】:Oracle string search performance issueOracle 字符串搜索性能问题
【发布时间】:2012-08-24 13:20:56
【问题描述】:

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

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%";

任何建议将不胜感激。

【问题讨论】:

  • 除了下面的答案之外,如果在文本列中搜索词的位置存在一致的规则,您可以考虑使用基于函数的索引。例如。如果波士顿(或任何其他搜索词)从位置 X 开始或在(第 1、第 2 等)空间之后。然后将您的 where 谓词与索引函数匹配可以导致使用该函数。

标签: oracle performance indexing hint


【解决方案1】:

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

Oracle does support full text search 但您必须使用 Oracle Text,这需要您在 name 列上构建 Oracle Text 索引并使用 CONTAINS operator 进行搜索,而不是使用 LIKE 查询。 Oracle Text 是一款非常强大的产品,因此在构建索引、刷新索引和构建查询方面有很多选择,具体取决于您想要获得的复杂程度。

您的索引提示未正确指定。假设在name 上有一个索引,该索引的名称是name_idx,并且您想强制对索引进行全面扫描(重申一下,如果出现以下情况,则对索引进行范围扫描不是一个有效选项有一个前导通配符),你需要类似

select /*+ index(travel_websites name_idx) */ description
  from travel_websites
 where name like '%boston%'

但是,不能保证全索引扫描会比全表扫描更有效。并且完全有可能优化器已经在没有提示的情况下选择了索引全扫描(您没有指定三个查询的查询计划是什么)。

【讨论】:

    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-04-08
      • 2013-03-18
      • 2012-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多