web-dev-qa-db-ja.com

外部キーはOracleのパフォーマンスに影響しますか?

外部キーのインデックスを作成するかどうか(当然のことですが)に関係なく、外部キーがあるとOracleデータベースのパフォーマンスに影響がありますか?

私が疑問に思っていた特定の領域は、データベースがより良いクエリプランを作成するのに役立つかどうかでした

5
Edd

はい。

データベースにRIが適用されている場合、オプティマイザはクエリから冗長なテーブルを削除できます。

たとえば、次の2つのテーブルがあります。

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
);

2番目には、最初の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;

したがって、T2のカウントは、2つのテーブルの結合と同じ数の行を返します。

select count(*) from t2;

COUNT(*)   
      1000 

select count(*)
from   t1
join   t2
on     t1.t1_id = t2.t1_id;

COUNT(*)   
      1000 

しかし、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")

しかし、外部キーをミックスに追加します。

alter table t2 add constraint fk foreign key ( t1_id ) references t1 ( t1_id );

そして、t1に存在しないt2の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 |   
------------------------------------------------------------------------------------- 

ひどい!なくなった! :)

8
Chris Saxon