Edd*_*Edd 5 performance oracle foreign-key execution-plan query-performance
无论您是否为外键创建索引(当然应该这样做),拥有外键对 Oracle 数据库的性能有任何影响吗?
我想知道的一个特定领域是它们是否有助于数据库生成更好的查询计划
是的。
当在数据库中强制执行 RI 时,优化器可以从查询中删除冗余表。
例如,这里有两个表:
create table t1 (
t1_id int not null primary key
);
create table t2 (
t2_id int not null primary key,
t1_id int not null
);
Run Code Online (Sandbox Code Playgroud)
第二个只包含第一个的 t1_ids:
insert into t1
select level from dual
connect by level <= 100;
insert into t2
select rownum, t1_id
from t1, (
select * from dual connect by level <= 10
);
commit;
Run Code Online (Sandbox Code Playgroud)
因此,T2 的计数返回与两个表的连接相同的行数:
select count(*) from t2;
COUNT(*)
1000
select count(*)
from t1
join t2
on t1.t1_id = t2.t1_id;
COUNT(*)
1000
Run Code Online (Sandbox Code Playgroud)
但是没有定义 FK :(
所以优化器不知道这一点。并且在执行查询时需要访问两个表:
set serveroutput off
select /*+ gather_plan_statistics */count(*)
from t1
join t2
on t1.t1_id = t2.t1_id;
COUNT(*)
1000
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST'));
PLAN_TABLE_OUTPUT
SQL_ID 8p235qbxm8yn0, child number 0
-------------------------------------
select /*+ gather_plan_statistics */count(*) from t1 join t2 on
t1.t1_id = t2.t1_id
Plan hash value: 3484656271
----------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
----------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 10 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 10 |
| 2 | NESTED LOOPS | | 1 | 1000 | 1000 |00:00:00.01 | 10 |
| 3 | TABLE ACCESS FULL| T2 | 1 | 1000 | 1000 |00:00:00.01 | 6 |
|* 4 | INDEX UNIQUE SCAN| SYS_C0014412 | 1000 | 1 | 1000 |00:00:00.01 | 4 |
----------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("T1"."T1_ID"="T2"."T1_ID")
Run Code Online (Sandbox Code Playgroud)
但是在混合中添加一个外键:
alter table t2 add constraint fk foreign key ( t1_id ) references t1 ( t1_id );
Run Code Online (Sandbox Code Playgroud)
它现在知道 t2 中不能有任何 t1 中不存在的 t1_id 值。所以它可以忽略t1:
select /*+ gather_plan_statistics */count(*)
from t1
join t2
on t1.t1_id = t2.t1_id;
COUNT(*)
1000
select *
from table(dbms_xplan.display_cursor(null, null, 'IOSTATS LAST'));
PLAN_TABLE_OUTPUT
SQL_ID 8p235qbxm8yn0, child number 0
-------------------------------------
select /*+ gather_plan_statistics */count(*) from t1 join t2 on
t1.t1_id = t2.t1_id
Plan hash value: 476902662
-------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1 |00:00:00.01 | 6 |
| 1 | SORT AGGREGATE | | 1 | 1 | 1 |00:00:00.01 | 6 |
| 2 | TABLE ACCESS FULL| T2 | 1 | 1000 | 1000 |00:00:00.01 | 6 |
-------------------------------------------------------------------------------------
Run Code Online (Sandbox Code Playgroud)
噗!它消失了!:)
归档时间: |
|
查看次数: |
2645 次 |
最近记录: |