2013-03-22 60 views
4

我想了解在Oracle的解释计划,想知道而形成的解释计划了解在Oracle的解释计划

我是测试在HR模式目前在Oracle 11g中

一个简单的查询哪些条件甲骨文认为
select * from countries 
where region_id in (select region_id from regions where region_name = 'Europe'); 

当我运行以下查询:

explain plan for 
select * from countries 
where region_id in (select region_id from regions where region_name = 'Europe'); 

SELECT * FROM table(dbms_xplan.display(null,null,'basic')); 

我在解释表下面的输出:

-------------------------------------------------------- 
| Id | Operation     | Name   | 
-------------------------------------------------------- 
| 0 | SELECT STATEMENT    |     | 
| 1 | NESTED LOOPS    |     | 
| 2 | INDEX FULL SCAN   | COUNTRY_C_ID_PK | 
| 3 | TABLE ACCESS BY INDEX ROWID| REGIONS   | 
| 4 | INDEX UNIQUE SCAN   | REG_ID_PK  | 
-------------------------------------------------------- 

在这里,我观察到,外部查询被首先执行,即国家表首先执行如用行3.

现在我增加了一个索引上的区域表的REGION_NAME跑解释计划再次 ,得到了下面的输出现在

-------------------------------------------------------------- 
| Id | Operation     | Name     | 
-------------------------------------------------------------- 
| 0 | SELECT STATEMENT    |      | 
| 1 | NESTED LOOPS    |      | 
| 2 | TABLE ACCESS BY INDEX ROWID| REGIONS    | 
| 3 | INDEX RANGE SCAN   | REGIONNAME_REGIONS_IX | 
| 4 | INDEX UNIQUE SCAN   | COUNTRY_C_ID_PK  | 
| 5 | INDEX RANGE SCAN   | COUNTRIES_REGIONID_IX | 
-------------------------------------------------------------- 

我的问题是:

  1. 应该不是内部查询首先执行,不管索引是否存在
  2. 如果添加索引改变执行计划,还有哪些其他功能可以改变它?
  3. 在一般情况下,执行过程是什么样的,它是顺序的(首先执行首先发生的连接,然后进入查询中的下一个连接)?

在此先感谢您的帮助。

-Varun

回答

2

解释计划严重依赖基于成本的优化器(CBO)。您可以通过收集您正在查询的表格上的统计数据来帮助完成此过程。关于为什么指数会改变计划,这是因为您已经向CBO提供了以前没有的重要信息。这相当于我问你这个问题:

没有索引:
“街道在哪里?” “

有了索引:
”哪里有一个蓝色的房子呢?

第二个问题提供了更大的上下文,因此您可以更快地推断出结果,而且您​​不必枚举所有这些街道上的东西。

您可以提供提示,查询即:

select /*+ parallel */ * from table
给予提示并行运行此查询。

对于第三个问题,我想是Oracle流程的一部分,并且没有记录供世界使用。

在第一个问题中,不一定,它都是基于成本的。

1

我不知道他们是否改变了11g执行计划输出中的任何内容,但是您确定您向我们展示了正确的查询吗?您正在从表国家中选择所有列(select *),但解释计划不显示任何表访问?还是COUNTRY_C_ID_PK包含所有列?

我希望下面的计划(不包括指数):

SELECT 
    NESTED LOOP 
    FULL TABLE SCAN (regions) 
    TABLE ACCESS BY INDEX ROWID (countries) 
     INDEX RANGE SCAN (COUNTRIES_REGIONID_IX) 

有了索引,我希望这样的事情:

SELECT 
    NESTED LOOP 
    TABLE ACCESS BY INDEX ROWID (regions) 
     INDEX RANGE SCAN (REGIONNAME_REGIONS_IX) 
    TABLE ACCESS BY INDEX ROWID (countries) 
     INDEX RANGE SCAN (COUNTRIES_REGIONID_IX) 

对于您的问题:

  1. Oracle可能会根据可用的统计信息从内部或外部查询中驱动查询
  2. 有很多东西影响执行计划...
  3. Oracle一次只能连接两个表(或行源)。加入的结果也是可以加入到下一个表格的行来源
1

基于成本的优化器会经历几个阶段,包括查询转换。您的查询几乎肯定由优化重写:

选择国家* 从国家加入上(countries.region_id = regions.region_id) 其中regions.region_name =“欧洲”的区域。

因此,原始查询中表示的内部和外部查询的概念可能不适用于转换后。顺便说一下,这就是为什么涉及EXISTS()和IN()的争论经常没有实际意义 - 两种情况下的查询通常都可以重写为连接。

之间信息的优化器使用(取决于版本)是:

  1. 在桌子上
  2. 统计数据表中的列统计
  3. 表列的
  4. 直方图值指标
  5. 存在
  6. 指数的大小和类型以及统计指数 - 特别是聚类因子
  7. 存在的约束 - 包括非空和检查约束。
  8. 每秒单块和多块读取和cpu操作的估计成本。
  9. 分区
  10. 物化视图和/或查询重写声明的存在和状态。
  11. 以前版本的查询的性能。

所以简而言之,不要惊讶于优化器所做的任何事情。这是一个非常复杂的工具包。