我想你的表有一个非常大量的行与一个给定的键(让我们称之为'B'
)和少量的行与其他键。
请注意,索引访问将仅适用于条件FIELD1 <> 'B'
,所有其他谓词将返回'B',因此不适合索引访问。
还要注意的是,如果你有一个以上的大键,索引的访问将不会从同一工作的原因所在 - 你将永远不会只有几个记录,其中指数可以获利。
以此为起点,你可以reformulte谓语
FIELD1 <> V_FIELD
为
DECODE(FIELD1,V_FIELD,1,0) = 0
的DECODE
返回1,如果FIELD1 = V_FIELD
并返回0,如果FIELD1 <> V_FIELD
这种转变可以让你定义一个基于函数的索引与DECODE
表达式。
例
create table tt as
select
decode(mod(rownum,10000),1,'A','B') FIELD1
from dual connect by level <= 50000;
select field1, count(*) from tt group by field1;
FIELD1 COUNT(*)
------ ----------
A 5
B 49995
FBIndex
create index tti on tt(decode(field1,'B',1,0));
使用您大型骨干用于索引定义。
访问
要选择FIELD1 <> 'B'
使用新配方谓语decode(field1,'B',1,0) = 0
这很好地导致一个索引访问:
EXPLAIN PLAN SET STATEMENT_ID = 'jara1' into plan_table FOR
SELECT * from tt where decode(field1,'B',1,0) = 0;
SELECT * FROM table(DBMS_XPLAN.DISPLAY('plan_table', 'jara1','ALL'));
------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 471 | 2355 | 24 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| TT | 471 | 2355 | 24 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | TTI | 188 | | 49 (0)| 00:00:01 |
------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access(DECODE("FIELD1",'B',1,0)=0)
要选择FIELD1 <> 'A'
使用新配方谓语decode(field1,'A',1,0) = 0
这里你不想索引访问,因为几乎整个表被返回 - 并且CBO打开FULL TABLE SCAN。
EXPLAIN PLAN SET STATEMENT_ID = 'jara1' into plan_table FOR
SELECT * from tt where decode(field1,'A',1,0) = 0;
SELECT * FROM table(DBMS_XPLAN.DISPLAY('plan_table', 'jara1','ALL'));
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 47066 | 94132 | 26 (4)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| TT | 47066 | 94132 | 26 (4)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(DECODE("FIELD1",'A',1,0)=0)
绑定变量
这会工作,即使你使用绑定变量FIELD1 <> V_FIELD
以同样的方式 - 只要你总是传递相同的值。
bind variable peeking将评估第一个解析中的正确计划并生成适当的计划。
如果要使用一个以上的值作为绑定变量(因此期望得到不同的值不同的计划) - 你将学到的adaptive cursor sharing
我们如何获得解释计划查询? –
在sqlplus中执行此操作:alter session set statistics_level = ALL;运行查询;然后运行select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));然后通过执行计划的输出 – BobC
问题知道如何获得“解释计划”或质疑我的问题? – 5frags