运行执行计划而不收集表统计信息(使用dbms_stat.gather_table_stat)和收集表统计信息然后运行执行计划将对执行计划进行任何更改。有人请说明收集表统计信息以及执行计划如何依赖于收集统计信息
答案 0 :(得分:0)
执行计划基于统计数据。如果您知道它并且以下示例对您没有用,请说出来并且我将删除此帖子。谢谢。 例如,我创建了两个表:
create table ag_test1 (id1 number, val varchar2(50));
alter table ag_test1 add constraint pk_ag_test1 primary key (id1);
create table ag_test2 (id2 number, val varchar2(50));
alter table ag_test2 add constraint pk_ag_test2 primary key (id2);
之后我收集了这些表格的统计数据:
begin
dbms_stats.gather_table_stats(ownname => user,tabname => 'AG_TEST1', cascade =>true);
dbms_stats.gather_table_stats(ownname => user,tabname => 'AG_TEST2', cascade =>true);
end;
运行查询:
select /* test_query_1 */
t1.val as tbl1, t2.val as tbl2
from ag_test1 t1
join ag_test2 t2 on (t1.id1 = t2.id2);
查看执行计划(因为你记得表包含0行):
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | NESTED LOOPS | | 1 | 80 | 2 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 1 | 80 | 2 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL | AG_TEST1 | 1 | 40 | 2 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | PK_AG_TEST2 | 1 | | 0 (0)| |
| 5 | TABLE ACCESS BY INDEX ROWID| AG_TEST2 | 1 | 40 | 0 (0)| |
--------------------------------------------------------------------------------------------
让我们填写此表(每行包含1M行):
insert all
when 1=1 then
into ag_test1 (id1, val)
values (lvl, val1)
when 1=1 then
into ag_test2 (id2, val)
values (lvl, val2)
select level as lvl, 'TBL1_VAL_'||level as val1, 'TBL2_VAL_'||level as val2
from dual
connect by level <=1000000;
commit;
再次运行查询并查看:
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | 2 (100)| |
| 1 | NESTED LOOPS | | 1 | 80 | 2 (0)| 00:00:01 |
| 2 | NESTED LOOPS | | 1 | 80 | 2 (0)| 00:00:01 |
| 3 | TABLE ACCESS FULL | AG_TEST1 | 1 | 40 | 2 (0)| 00:00:01 |
|* 4 | INDEX UNIQUE SCAN | PK_AG_TEST2 | 1 | | 0 (0)| |
| 5 | TABLE ACCESS BY INDEX ROWID| AG_TEST2 | 1 | 40 | 0 (0)| |
--------------------------------------------------------------------------------------------
什么都没改变。 1M行的执行计划等于0行。因为Oracle使用软解析(查找并使用以前的计划)。让我们使用no_invalidate子句收集统计信息( no_invalidate =&gt; false ):
begin
dbms_stats.gather_table_stats(ownname => user,tabname => 'AG_TEST1', cascade =>true, no_invalidate => false);
dbms_stats.gather_table_stats(ownname => user,tabname => 'AG_TEST2', cascade =>true, no_invalidate => false);
end;
查看执行计划:
---------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes |TempSpc| Cost (%CPU)| Time |
---------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | | | | 5120 (100)| |
|* 1 | HASH JOIN | | 1000K| 40M| 31M| 5120 (1)| 00:00:01 |
| 2 | TABLE ACCESS FULL| AG_TEST1 | 1000K| 20M| | 995 (1)| 00:00:01 |
| 3 | TABLE ACCESS FULL| AG_TEST2 | 1000K| 20M| | 995 (1)| 00:00:01 |
---------------------------------------------------------------------------------------