我试图了解oracle中的解释计划,并想知道oracle在制定解释计划时考虑的条件
我正在测试oracle 11g中存在的HR模式中的简单查询
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行所示。
现在我在regions表的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 |
--------------------------------------------------------------
现在我的问题是:
提前感谢您的帮助。
-Varun
答案 0 :(得分:2)
解释计划在很大程度上依赖于基于成本的优化器(CBO)。您可以通过收集要查询的表的统计信息来帮助完成此过程。现在就索引为什么会改变计划而言,这是因为你已经向CBO提供了之前没有的关键信息。这相当于我问你这个问题:
无索引:
“街道在哪里?”
索引:
“那里有蓝色房子的街道在哪里?”
第二个问题提供了更大的背景,因此你可以更快地演绎,而且你不必枚举所有这些街道上的东西。
您可以向查询提供提示,即:
select /*+ parallel */ * from table
提供提示以并行运行此查询。
对于第三个问题,我认为这是一个Oracle流程,并没有记录供全世界使用。
在第一个问题中,并非必然,它都是基于成本的。
答案 1 :(得分: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)
对于你的问题:
答案 2 :(得分:1)
基于成本的优化工具经历了几个阶段,包括查询转换。您的查询几乎肯定会被优化器重写为:
选择国家。* 来自各国加入地区(countries.region_id = regions.region_id) regions.region_name ='Europe';
因此,原始查询中表示的内部和外部查询的概念可能不适用于转换后。顺便说一句,这就是为什么有关EXISTS()和IN()的论点经常没有实际意义 - 两种情况下的查询通常都可以重写为连接。
优化程序使用的信息(取决于版本)包括:
简而言之,不要对优化者做的任何事情感到惊讶。这是一个非常复杂的工具包。