我对执行速度非常慢的存储过程感到有些困惑。存储过程基本上包含一个使用传入参数 (in_id) 的查询,并放置在一个游标中,如下所示:
open tmp_cursor for
select col1, col2, col3
from table1 tab
where ((in_id is null) or (tab.id = in_id)); -- tab.id is the PK
当我使用预定义的值单独获得 SQL 查询的执行计划时,我通过使用索引的查询获得了良好的结果。但是,当我从我的应用程序调用该过程时,我看到没有使用索引并且表进行了完整扫描,从而导致性能下降。
如果我删除 WHERE 子句“(in_id is null)”的第一部分,应用程序的性能又会很快。
为什么在我的应用程序调用期间没有使用索引(传入 in_id)?
最佳答案
in_id is null
我在这里回答了类似的问题 https://stackoverflow.com/a/26633820/3989608
关于 NULL 值和 INDEX 的一些事实:
托马斯·凯特 (Thomas Kyte) 的演示的某些部分与此相关:
ops$tkyte@ORA9IR2> create table t
2 as
3 select object_id, owner, object_name
4 from dba_objects;
Table created.
ops$tkyte@ORA9IR2> alter table t modify (owner NOT NULL);
Table altered.
ops$tkyte@ORA9IR2> create index t_idx on t(object_id,owner);
Index created.
ops$tkyte@ORA9IR2> desc t
Name Null? Type
----------------------- -------- ----------------
OBJECT_ID NUMBER
OWNER NOT NULL VARCHAR2(30)
OBJECT_NAME VARCHAR2(128)
ops$tkyte@ORA9IR2> exec dbms_stats.gather_table_stats(user,'T');
PL/SQL procedure successfully completed.
好吧,当应用于 OBJECT_ID 时,该索引当然可以用于满足“IS NOT NULL”:
ops$tkyte@ORA9IR2> set autotrace traceonly explain
ops$tkyte@ORA9IR2> select * from t where object_id is null;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=34)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (Cost=3 Card=1 Bytes=34)
2 1 INDEX (RANGE SCAN) OF 'T_IDX' (NON-UNIQUE) (Cost=2 Card=1)
事实上——即使表没有任何 NOT NULL 列,或者我们不想/不需要有一个涉及 OWNER 的串联索引——有一种透明的方法可以很容易地找到 NULL OBJECT_ID 值:
ops$tkyte@ORA9IR2> drop index t_idx;
Index dropped.
ops$tkyte@ORA9IR2> create index t_idx_new on t(object_id,0);
Index created.
ops$tkyte@ORA9IR2> set autotrace traceonly explain
ops$tkyte@ORA9IR2> select * from t where object_id is null;
Execution Plan
----------------------------------------------------------
0 SELECT STATEMENT Optimizer=CHOOSE (Cost=3 Card=1 Bytes=34)
1 0 TABLE ACCESS (BY INDEX ROWID) OF 'T' (Cost=3 Card=1 Bytes=34)
2 1 INDEX (RANGE SCAN) OF 'T_IDX_NEW' (NON-UNIQUE) (Cost=2 Card=1)
来源:Something about nothing by Thomas Kyte
关于sql - 存储过程 SQL 执行计划,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29630354/