Oracle 查询和函数索引使用的串联

Raf*_*tro 6 index oracle explain

我对 Oracle 11g 中的索引有一些我无法理解的问题。

我们可以创建测试数据:

create table test2(field1 varchar2(100),field2 varchar2(100),field3 number,field4 varchar2(100)); 

create index test2_idx1 on test2(upper(field1)); 

create index test2_idx1b on test2(field1); 

create index test2_idx2 on test2(field3); 

DECLARE
  j NUMBER :=1;
BEGIN
  FOR i IN 1..500000
  LOOP
    INSERT
    INTO test2 
    (field1,field2, field3, field4)
    VALUES 
    ('field1='||i,'a', j, '??i' );

    IF (i mod 1000)=0 THEN
       j := j+1;
    END IF;
  END LOOP;
  COMMIT;
END;


EXEC DBMS_STATS.GATHER_TABLE_STATS ('system', 'test2');
Run Code Online (Sandbox Code Playgroud)

然后我制定了一些解释计划,结果我无法理解

查询 1

SELECT * FROM test2 WHERE field3=1;
Run Code Online (Sandbox Code Playgroud)

解释计划:

解释查询 01 的计划

这里一切正常。使用索引。

查询 2

SELECT * FROM test2 WHERE upper(field1)='FIELD1=1';
Run Code Online (Sandbox Code Playgroud)

解释计划

解释查询 2 的计划

一切正常。使用索引。

查询 3

SELECT /*+ USE_CONCAT */ * FROM test2 WHERE field1='FIELD1=1' OR field3=1;
Run Code Online (Sandbox Code Playgroud)

解释计划

解释查询 3 的计划

索引用于连接。没问题了。

查询 4

SELECT /*+ USE_CONCAT */ * FROM test2 WHERE upper(field1)='FIELD1=1' OR field3=1;
Run Code Online (Sandbox Code Playgroud)

解释计划

解释查询 4 ​​的计划

这里出现了我的问题。为什么不使用 test2_idx1?是不是因为它是一个函数索引?在这种情况下有什么解决方法吗?

非常感谢。

Jac*_*las 5

这似乎是优化器的限制(或者可能是错误)。

此查询的计划:

SELECT /*+ USE_CONCAT */ * FROM test2 WHERE upper(field1)='FIELD1=1' OR field3=1
union all
(
SELECT * FROM test2 WHERE upper(field1)='FIELD1=1'
union all
SELECT * FROM test2 WHERE field3=1
);
Run Code Online (Sandbox Code Playgroud)

解释

表明这不是错误统计数据的错,并且还演示了使用的解决方法union all(但请注意,您需要类似upper(field1)='FIELD1=1 and (field3 is null or field3<>1)完全等效的查询)

(我的测试是在 10.2 上)