我在Oracle 11g数据库中有一个表,其中的一列中包含未格式化的文本,输入时应显示该表。无论如何,用户应能够以任何可能的格式(关于标点符号)搜索该文本。我通过在列上引入基于函数的索引来满足该要求:

CREATE INDEX "MY_REGEX_INDEX" ON "MY_TABLE" (UPPER( REGEXP_REPLACE ("MY_COLUMN",'[:punct:]','')))


当我查询该索引

SELECT * FROM MY_TABLE
WHERE UPPER(REGEXP_REPLACE(,'[:punct:]', ''))='123'


它工作正常。执行计划包含正确使用了我的新索引(且高度选择性)。

但是,当我将绑定变量用于正则表达式模式时,它将不再起作用。

SELECT * FROM MY_TABLE
WHERE UPPER(REGEXP_REPLACE(,:pattern, ''))='123'


模式变量包含恒定的模式,但是无论如何,优化器都会拒绝使用索引。不知何故,Oracle的绑定窥视无法开始。

不幸的是,我不可能不使用文字而不是绑定变量,因为我的应用程序使用Hibernate来生成SQL。提示也没有解决。

我不是Oracle专家-有什么方法可以使Oracle“了解”我的绑定变量并使用索引?在文档中没有找到与我的主题相关的任何东西,除了我实际上可以为模式使用绑定变量这一事实。

任何帮助都将受到高度赞赏。

最佳答案

尽管它不能回答为什么绑定变量会停止使用索引,或者为什么会忽略提示(我已进行了验证,但是Oracle可以随意忽略我认为的提示-故名),但是您可以采取另一种方法并改用虚拟列:

drop index my_regex_index;

alter table my_table add my_regexp_column generated always
  as (upper(regexp_replace(my_column, '[[:punct:]]')));

create index my_regex_index on my_table (my_regexp_column);


然后,查询将使用该索引,因为无需担心绑定,也无需传递额外的(常量)值:

select * from my_table where my_regexp_column = '123';

----------------------------------------------------------------------------------------------
| Id  | Operation                   | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                |     1 |   204 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| MY_TABLE       |     1 |   204 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | MY_REGEX_INDEX |     1 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------------


当然,这假设您可以添加列,并且Hibernate会正确处理它。我不明白为什么不这样做,但我不使用它...

关于java - Oracle不会对具有绑定(bind)变量的regex_replace使用基于函数的索引,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/22614943/

10-10 01:23
查看更多