为什么Oracle SQL Optimizer会忽略此视图的索引谓词?
我正在尝试优化一组存储过程,这些过程与包括此视图在内的许多表相冲突。这种看法是这样的: 我们有TBL_A id、hist_date、hist_type和其他两种行类型的列:hist_type“O”和hist_type“N”。视图将表A自连接到自身,并将N行与对应的O行进行转换。如果O行不存在N行,则重复O行值。像这样:为什么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
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。。。。。