Oracle 基于函数的索引和 CASE 语句

标签 oracle function indexing

我有一个包含三个互斥列的表。

create table key_tab
(
  a_key number null,
  b_key number null,
  c_key number null,
  key_tab_key number not null <-- Primary Key
)
/

示例:当填充 A_KEY 时,B_KEY 和 C_KEY 都为空。

我有一个 SELECT 语句如下:

select CASE INP_KEY 
    WHEN 'A' THEN 
       select A_KEY from KEY_TAB where A_KEY=:2 AND KEY_TAB_KEY =:3 
    WHEN 'B' THEN 
       select B_KEY from KEY_TAB where B_KEY=:2 and KEY_TAB_KEY = :3
    WHEN 'C' then
       select C_KEY from KEY_TAB where C_KEY=:2 and KEY_TAB_KEY = :3
END FROM dual

我创建了一个基于函数的索引,如下所示:

unique index key_tab_ix on key_tab
( case when a_key is not null then a_key
       when b_key is not null then b_key
       when c_key is not null then c_key
  end,
  key_tab_key

我有一个进程读取临时表,然后查询 KEY_TAB。如果未找到记录,则会将该记录插入到 KEY_TAB 中。

对于前 100 条记录,该过程运行速度非常快,然后速度急剧减慢。这可能是因为最初有很多记录需要搜索,但随着表的增长 - 它有更多的记录需要搜索。而且该索引似乎没有帮助。

任何帮助将不胜感激。

最佳答案

如果保证 a_key、b_key 和 c_key 中只有一个不为空(例如使用检查约束),那么您可以将唯一索引创建为:

create unique index key_tab_ix on key_tab (coalesce(a_key,b_key,c_key));

我会将您的选择语句更改为以下内容:

select A_KEY from KEY_TAB where A_KEY=:2 AND KEY_TAB_KEY = :3 and INP_KEY = 'A'
union all
select B_KEY from KEY_TAB where B_KEY=:2 and KEY_TAB_KEY = :3 and INP_KEY = 'B'
union all
select C_KEY from KEY_TAB where C_KEY=:2 and KEY_TAB_KEY = :3 and INP_KEY = 'C'

或者您甚至可以删除 和 INP_KEY = '?' 谓词并将其进一步简化为:

select coalesce(a_key,b_key,c_key)
  from KEY_TAB
 where coalesce(a_key,b_key,c_key) = :2
   and KEY_TAB_KEY = :3

特别是因为您已经在上面的 coalesce(a_key,b_key,c_key) 上创建了索引。

关于Oracle 基于函数的索引和 CASE 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32489310/

相关文章:

javascript - 如何按顺序处理函数而不是同时处理所有函数

r - 对 data.frame 中的每一行应用一个函数,并将结果附加到 R 中的 data.frame

mysql - 我应该在频繁获取新行的 MySQL 表上放置索引吗

sql - Oracle 中是否有等同于 TRY_CONVERT() 的函数?

sql - 如何使用 oracle 查询获取最后一个和倒数第二个日期

sql - Oracle SQL : How add IF condition inside FORALL LOOP

javascript - ES6 类方法在 forEach 循环内不返回任何内容

python - 在python中用numpy识别一列中具有相同值的向量

mysql 索引以获得更好的选择性能

sql - 有没有办法强制 Oracle 在不使用提示的情况下更改查询计划?