我们正在使用Oracle 11g数据库 您可能知道或者可能不知道,如果您在字符串前面使用带有“%”的通配符查询,则索引未被使用,全表扫描是发生。
看起来似乎没有关于如何改进此类查询的明确建议,但也许您可以根据您的经验分享一些有价值的信息,如何优化以下查询:
SELECT *
FROM myTable
WHERE UPPER(CustomerName) like '%ABC%'
OR UPPER(IndemnifierOneName) like '%ABC%'
OR UPPER(IndemnifierTwoName) like '%ABC%';
...其中所有3列的类型为 varchar2(100), ABC 是变量输入参数的值。
@All建议 CONTEX 索引,请注意我的数据每天的任何时间都会更新,并且此索引需要重新同步,因此不是一个不错的选择对于 150万行的表格,抱歉。
P.S。我会回答所有答案,所以请保持他们的到来。
答案 0 :(得分:7)
如前所述,您可以在名称列中添加ctx上下文索引。
假设有少量记录得到更新,1个选项是每天刷新您的索引。 (并在发生时记录)
然后添加lastupdate日期列&正在搜索的表的索引。
应该可以扫描ctx索引以查找大多数旧的未更改数据 并使用传统的LIKE从较小百分比的更新数据中进行选择 e.g:
WHERE (lastupdated<lastrefresh AND contains(name,'%ABC%'))
OR (lastupdated>lastrefresh AND name like '%ABC%')
注意:您可能会发现您的查询计划有点精神错乱(很多位图转换为行ID),在这种情况下,将OR的2部分拆分为UNION ALL查询。 e.g
SELECT id FROM mytable
WHERE
(lastupdate>lastrefresh and name LIKE '%ABC%')
UNION ALL
SELECT id FROM mytable
WHERE lastupdate<lastrefresh and CONTAINS(name, '%ABC%', 1) > 0
答案 1 :(得分:6)
唯一的优化是不使用该类型的查询,而是使用数据库平台的本机功能:
请参阅Oracle Text:http://www.oracle.com/technetwork/database/enterprise-edition/index-098492.html
SQL Server相关问题的常见答案是全文搜索..很高兴看到Oracle有一些好的或更好的东西。
答案 2 :(得分:3)
UPPER()
在任何事情之前杀死你的索引,考虑使用正则表达式。初始%
可以避免正常的索引扫描,但并不总是导致全表扫描,而是进入全指数扫描,这比FTS快。
我认为'ABC'
是可变的。如果没有,则可以使用函数索引。
答案 3 :(得分:0)
有时这种查询是不可避免的 - 从URL中提取域,或者从带有前缀和后缀的单词中提取根。
您可以使用或不使用自定义标记生成器来使用全文索引。
或者,如果您要搜索的字符串数量有限并且事先已知(例如,您正在处理需要从URL中提取的一组有限的域名),您可以使用确定性函数被索引。
http://www.akadia.com/services/ora_function_based_index_2.html
答案 4 :(得分:-2)
使用Oracle文本但稍微更新的CTXCAT变体 - 此域索引作为插入/更新相关行的事务的一部分进行更新,因此始终是最新的 - 有关详细信息,请参阅Oracle自己的Oracle Text文档。