【问题标题】:Oracle Function Based Indexes and CASE StatementOracle 基于函数的索引和 CASE 语句
【发布时间】:2015-12-05 23:58:09
【问题描述】:

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

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 条记录,该过程运行得非常快,然后急剧变慢。这可能是因为最初有很多记录要搜索,但随着表的增长 - 它有更多记录要搜索。而且索引似乎没有帮助。

任何帮助将不胜感激。

【问题讨论】:

  • 如果 key_tab_key 是唯一索引支持的主键,我希望它比 a_key、b_key 或 c_key 上的任何索引更具选择性。我会检查查询计划以查看它是否使用了该唯一索引,如果没有,为什么不使用。

标签: oracle function indexing


【解决方案1】:

如果保证 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'

或者您甚至可以删除 and 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) 上创建索引。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-05
    • 2011-09-15
    • 2023-02-07
    • 1970-01-01
    • 2017-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多