为什么Oracle SQL Optimizer会忽略此视图的索引谓词?

为什么Oracle SQL Optimizer会忽略此视图的索引谓词?,sql,oracle,view,indexing,Sql,Oracle,View,Indexing,我正在尝试优化一组存储过程,这些过程与包括此视图在内的许多表相冲突。这种看法是这样的: 我们有TBL_A id、hist_date、hist_type和其他两种行类型的列:hist_type“O”和hist_type“N”。视图将表A自连接到自身,并将N行与对应的O行进行转换。如果O行不存在N行,则重复O行值。像这样: CREATE OR REPLACE FORCE VIEW V_A (id, hist_date, hist_type, other_columns_o, other_column

我正在尝试优化一组存储过程,这些过程与包括此视图在内的许多表相冲突。这种看法是这样的:

我们有TBL_A id、hist_date、hist_type和其他两种行类型的列:hist_type“O”和hist_type“N”。视图将表A自连接到自身,并将N行与对应的O行进行转换。如果O行不存在N行,则重复O行值。像这样:

CREATE OR REPLACE FORCE VIEW V_A (id, hist_date, hist_type, other_columns_o, other_columns_n)
select 
o.id, o.hist_date, o.hist_type, 
o.other_columns as other_columns_o,
case when n.id is not null then n.other_columns else o.other_columns end as other_columns_n
from
TBL_A o left outer join TBL_A n
on o.id=n.id and o.hist_date=n.hist_date and n.hist_type = 'N'
where o.hist_type = 'O';
TBL_A有一个唯一的索引:id、历史日期、历史类型。它还有一个唯一的索引:hist_date、id、hist_type,这是主键

以下查询在存储过程中存在问题,其中x声明为类型\u TABLE\u,其编号为:

select b.id BULK COLLECT into x from TBL_B b where b.parent_id = input_id;

select v.id from v_a v
where v.id in (select column_value from table(x))
and   v.hist_date = input_date
and   v.status_new = 'CLOSED';
当访问TBL_A时,此查询忽略id列上的索引,而是使用日期进行范围扫描,以拾取该日期的所有行。然后,它使用数组中的值过滤设置。但是,如果我简单地将ID列表作为一个数字列表给出,那么优化器会很好地使用索引:

select v.id from v_a v
where v.id in (123, 234, 345, 456, 567, 678, 789)
and   v.hist_date = input_date
and   v.status_new = 'CLOSED';

当直接反对TBL_A时,这个问题也不存在,我有一个解决方法可以做到这一点,但这并不理想。有没有办法让优化器首先检索数组值,并在访问表时将它们用作谓词?还是一个重组视图以实现这一目标的好方法

Oracle不使用索引,因为它假定从tablex选择列_值返回8168行

索引检索少量数据的速度更快。在某些情况下,扫描整个表比重复遍历索引树要快

估计一个常规SQL语句的基数是非常困难的。为程序代码创建准确的估计几乎是不可能的。但我不知道他们是从哪里找到8168的。在数据仓库中,表函数通常与流水线函数一起使用,大的数目是有意义的

可以生成更准确的估计,并可能生成使用该指数的计划

下面是一个错误基数估计的示例:

create or replace type type_table_of_number as table of number;

explain plan for
select * from table(type_table_of_number(1,2,3,4,5,6,7));
select * from table(dbms_xplan.display(format => '-cost -bytes'));

Plan hash value: 1748000095

-------------------------------------------------------------------------
| Id  | Operation                             | Name | Rows  | Time     |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |      |  8168 | 00:00:01 |
|   1 |  COLLECTION ITERATOR CONSTRUCTOR FETCH|      |  8168 | 00:00:01 |
-------------------------------------------------------------------------
以下是修复方法:

explain plan for select /*+ dynamic_sampling(2) */ *
                 from table(type_table_of_number(1,2,3,4,5,6,7));
select * from table(dbms_xplan.display(format => '-cost -bytes'));

Plan hash value: 1748000095

-------------------------------------------------------------------------
| Id  | Operation                             | Name | Rows  | Time     |
-------------------------------------------------------------------------
|   0 | SELECT STATEMENT                      |      |     7 | 00:00:01 |
|   1 |  COLLECTION ITERATOR CONSTRUCTOR FETCH|      |     7 | 00:00:01 |
-------------------------------------------------------------------------

Note
-----
   - dynamic statistics used: dynamic sampling (level=2)

如果您可以发布解释计划并显示索引定义,这将非常有帮助。是否加入pl/sql表帮助?您的第二个直接值查询可能会受益于inlist迭代器。今晚我将尝试发布解释计划和索引定义。请尝试。。。其中v.id在select/*+cardinalitytt中,7*/列_值来自表x tt。。。。。