[英]Oracle 12c - view plans access unnecessary tables
I am hoping for an explanation of some view + optimizer behavior我希望解释一些视图+优化器的行为
lets make a view like this让我们做一个这样的视图
select e.employee_name, e.employee_active, ei.marital_status
from employees e
left join employee_info ei on ei.employee_id = e.employee_id
Then lets access it like this然后让我们像这样访问它
select distinct employee_name from employee_view where employee_id = 13
In my head, I'm thinking we do not need to access employee_info table at all for this query to execute in a functionally correct way.在我的脑海中,我认为我们根本不需要访问employee_info 表来让这个查询以功能正确的方式执行。 Yet, when I explain plans on this query, I see it accessing employee_info.
然而,当我解释这个查询的计划时,我看到它访问了employee_info。 Am I missing something that makes it necessary to actually perform that join?
我是否遗漏了一些需要实际执行该连接的东西? If it is functionally equivalent to not hit that table, is there a way to stop that from happening in 12c?
如果它在功能上等同于不打那张桌子,有没有办法阻止这种情况在 12c 中发生?
You deduction is basically correct, but you must take in account than not every optimization that is possible is also implemented .您的推论基本上是正确的,但您必须考虑到并非所有可能的优化都已实现。
Oracle pragmatically observes the potential and decides where the optimization should be extended. Oracle 务实地观察潜力并决定应该在哪里扩展优化。
For example there were times where the predicate where 1=1 and...
could confuse the optimizer, but as this "construction" is used rather often, in recent version the optimizer recognised it and ignore it without side effects.例如,有时
where 1=1 and...
的谓词可能会使优化器感到困惑,但由于这种“构造”被经常使用,在最近的版本中,优化器识别它并忽略它而没有副作用。
Your setup of outer join to child, while selecting distinct
from the parent columns only is probably not very frequent and therefore not yet covered.您对子项的外部连接设置,虽然仅选择与父列
distinct
,但可能不是很频繁,因此尚未涵盖。
Here a similar example, where Oracle can skip a table from a view (Note the PK
and FK
definition, which is crutial )这里有一个类似的例子,其中 Oracle 可以从视图中跳过一个表(注意
PK
和FK
定义,这是至关重要的)
create table employees (
employee_id int primary key,
employee_name varchar2(10),
employee_active varchar2(10));
create table employee_info (
employee_id int,
marital_status varchar2(10));
alter table employee_info
add constraint emp_info_fk1 foreign key (employee_id)
references employees (employee_id);
create or replace view employee_view as
select e.EMPLOYEE_ID, e.employee_name, e.employee_active, ei.marital_status
from employees e
join employee_info ei on ei.employee_id = e.employee_id;
The query select marital_status from employee_view where employee_id = 13
can skip the employees
(parent) table and access only the child table查询
select marital_status from employee_view where employee_id = 13
可以跳过employees
(父)表,只访问子表
-----------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-----------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 20 | 2 (0)| 00:00:01 |
|* 1 | TABLE ACCESS FULL| EMPLOYEE_INFO | 1 | 20 | 2 (0)| 00:00:01 |
-----------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("EI"."EMPLOYEE_ID"=13)
More information and links in similar answer更多信息和类似答案中的链接
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.