Performance 为什么Oracle在视图上采用另一个执行路径
我们正在使用oracle 10g数据库上的视图向.NET应用程序提供数据。这其中很好的一点是,我们需要在视图中使用一个数字(12),以便.NET应用程序将其视为一个整数。因此,在select中有一个Performance 为什么Oracle在视图上采用另一个执行路径,performance,oracle,view,oracle10g,Performance,Oracle,View,Oracle10g,我们正在使用oracle 10g数据库上的视图向.NET应用程序提供数据。这其中很好的一点是,我们需要在视图中使用一个数字(12),以便.NET应用程序将其视为一个整数。因此,在select中有一个强制转换(字段为数字(12))。到目前为止,如果我们在某些字段上使用where子句(0.9k),成本是很高的。但现在有趣的是,如果我们对此进行查看,并使用where子句查询该视图,则成本从0.9k增加到18k 在解释计划中,突然跳过了所有索引,这导致了大量的全表扫描。为什么在使用视图时会发生这种情况
强制转换(字段为数字(12))
。到目前为止,如果我们在某些字段上使用where子句(0.9k),成本是很高的。但现在有趣的是,如果我们对此进行查看,并使用where子句查询该视图,则成本从0.9k增加到18k
在解释计划中,突然跳过了所有索引,这导致了大量的全表扫描。为什么在使用视图时会发生这种情况
问题的简化版本:
SELECT CAST (a.numbers AS NUMBER (12)) numbers
FROM tablea a
WHERE a.numbers = 201813754;
解释计划:
Plan
SELECT STATEMENT ALL_ROWSCost: 1 Bytes: 7 Cardinality: 1
1 INDEX UNIQUE SCAN INDEX (UNIQUE) TAB1_IDX Cost: 1 Bytes: 7 Cardinality: 1
Plan
SELECT STATEMENT ALL_ROWSCost: 210 Bytes: 2,429 Cardinality: 347
1 TABLE ACCESS FULL TABLE TABLEA Object Instance: 2 Cost: 210 Bytes: 2,429 Cardinality: 347
没有问题,索引命中
如果我们将上述查询放在视图中并执行相同的查询:
SELECT a.numbers
FROM index_test a
WHERE a.numbers = 201813754;
没有使用索引。
解释计划:
Plan
SELECT STATEMENT ALL_ROWSCost: 1 Bytes: 7 Cardinality: 1
1 INDEX UNIQUE SCAN INDEX (UNIQUE) TAB1_IDX Cost: 1 Bytes: 7 Cardinality: 1
Plan
SELECT STATEMENT ALL_ROWSCost: 210 Bytes: 2,429 Cardinality: 347
1 TABLE ACCESS FULL TABLE TABLEA Object Instance: 2 Cost: 210 Bytes: 2,429 Cardinality: 347
问题是您正在将函数应用于列(在本例中为强制转换)。Oracle无法将您的索引用作查询状态。要解决此问题,您需要从视图中删除强制转换函数,或创建基于函数的索引:
create table tablea (numbers integer);
insert into tablea
select rownum from dual connect by level <= 1000;
create index ix on tablea (numbers);
-- query on base table uses index
explain plan for
SELECT * FROM tablea
where numbers = 1;
SELECT * FROM table(dbms_xplan.display(null,null, 'BASIC +PREDICATE'));
---------------------------------
| Id | Operation | Name |
---------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | INDEX RANGE SCAN| IX |
---------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access("NUMBERS"=1)
create view v as
SELECT cast(numbers as number(12)) numbers FROM tablea;
-- the cast function in the view means we can't use the index
-- note the filter in below the plan
explain plan for
SELECT * FROM v
where numbers = 1;
SELECT * FROM table(dbms_xplan.display(null,null, 'BASIC +PREDICATE'));
------------------------------------
| Id | Operation | Name |
------------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | TABLE ACCESS FULL| TABLEA |
------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter(CAST("NUMBERS" AS number(12))=1)
-- create the function based index and we're back to an index range scan
create index iv on tablea (cast(numbers as number(12)));
explain plan for
SELECT * FROM v
where numbers = 1;
SELECT * FROM table(dbms_xplan.display(null,null, 'BASIC +PREDICATE'));
---------------------------------
| Id | Operation | Name |
---------------------------------
| 0 | SELECT STATEMENT | |
|* 1 | INDEX RANGE SCAN| IV |
---------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - access(CAST("NUMBERS" AS number(12))=1)
创建表tablea(数字整数);
插入表A
从dual connect by level中选择rownum很可能是因为这种情况消除了Oracle使用索引的可能性。但是如果看不到实际的SQL和执行计划,就很难判断这一点