简体   繁体   English

Oracle 12c - 查看计划访问不必要的表

[英]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 可以从视图中跳过一个表(注意PKFK定义,这是至关重要的)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM