0

新しいプロジェクトを開始したばかりですが、外部キーの制約が3つしかない本番アプリケーションのOracle10gデータベースに直面しています。私は、外部キーの制約がないデータベースを見ることに慣れていません。FKを使用しないことには、パフォーマンス/同時実行性に関する考慮事項があるかもしれないと推測しています。その理由は、論理データベーススキーマでアーキテクトがすべての関係を指定しているが、これらの関係が外部キー制約としてデータベースに実装されていないためです。

質問:パフォーマンスに影響を与えないRELYNOVALIDATEを使用して外部キー制約を定義できることを読みました。関係を簡単に確認できるように、このデータベースにRELY FK制約を定義することは価値がありますか?このアプリケーションはORMを使用して構築されていませんが、外部キーなしで実行することは本当に価値がありますか?

データベースは以下の例で非正規化されています

表1:FINProduct(ID(数値)、説明(varchar(5))、FINproductCode(varchar(10))...)

表2:FINProductCode(ID(number、FINproductCode(varchar(10))、LastUpdated(datetime)...)

したがって、表1と表2の間に関係を持たせる代わりに、FINproductCode列は表1に複製されます。

飲むのは時期尚早ですが、必要だと思います!

4

3 に答える 3

2

外部キー制約がないことが、パフォーマンスの問題に対する合理的な対応であると仮定することには、非常に慎重です。外部キー制約の適用にはオーバーヘッドがありますが (特に適切なインデックスがない場合)、アプリケーションが Oracle よりも効率的に制約を検証できる可能性は非常に低いです。したがって、問題は、外部キー制約のオーバーヘッドを小さくしたいのか、データベースに無効なデータが挿入されることをほぼ確実にしたいのかということです。これがあなたが望むトレードオフである可能性は非常に低いでしょう。正しいデータをキャプチャするよりも少し速くても、不正確で理解できないデータを喜んでキャプチャするビジネス ユーザーにまだ会ったことがありません。 .

背景が大幅に増えない限り、欠落しているすべての外部キー制約を作成する傾向があります。制約を作成RELY NOVALIDATEすることは可能ですが、外部キー制約の主な利点、つまり無効なデータが最初にデータベースに入力されるのを防ぐことができなくなります。

于 2012-09-20T08:02:33.563 に答える
0

これは、文書化の目的でのみ FK を追加するか、無効な FK 値で将来の INSERT/UPDATE を防止するかによって異なります。

ドキュメントの目的でのみ必要な場合は、RELY NOVALIDATE を使用して FK 制約を作成し、後でそれを無効にします。そうしないと、Oracle は将来の INSERT/UPDATE をチェックします。

ただし、絶対に必要でない限り、これを行わないでください。

私は Justin Cave に同意します: ほとんどの場合、「プレーンな」FK 制約を追加するだけでよいので、既存のデータが正しいことを確認できます。

于 2012-09-20T08:14:19.823 に答える
0

制約を作成し、違反を例外テーブルに報告しようとします。データを修正し、制約を有効にします。

テストデータを作成する

create table parent (pk integer
                    ,data varchar2(1)
                    ,CONSTRAINT PARENT_PK PRIMARY KEY (PK)  ENABLE );

create table child (pk integer
                    ,pk_parent integer
                    ,data varchar2(1)
                    ,CONSTRAINT CHILD_PK PRIMARY KEY (PK)  ENABLE );

insert into parent values (1,'a');
insert into parent values (2,'b');


insert into child values (1,1,'a');
insert into child values (2,2,'b');
insert into child values (3,3,'c');

外部キー制約を作成します。

alter table child add constraint fk_parent foreign key(pk_parent) references parent(pk);

SQL Error: ORA-02298: Kan (ROB.FK_PARENT) niet valideren - bovenliggende sleutels zijn niet gevonden.
02298. 00000 - "cannot validate (%s.%s) - parent keys not found"
*Cause:    an alter table validating constraint failed because the table has
           child records.
*Action:   Obvious

「enable novalidate」オプションを使用して外部キーを作成します

alter table child add constraint fk_parent foreign key(pk_parent) references parent(pk) enable novalidate;
table CHILD altered.

insert into child values (4,4,'c');

SQL Error: ORA-02291: Integriteitsbeperking (ROB.FK_PARENT) is geschonden - bovenliggende sleutel is niet gevonden.
02291. 00000 - "integrity constraint (%s.%s) violated - parent key not found"
*Cause:    A foreign key value has no matching primary key value.
*Action:   Delete the foreign key or add a matching primary key.

FK に違反する新しいデータを挿入することはできません。

次に、FK 制約に違反しているテーブル内のデータを修正します。

例外テーブルを作成し、制約を有効にしてみます。

create table exceptions(row_id rowid,
                        owner varchar2(30),
                        table_name varchar2(30),
                        constraint varchar2(30));


ALTER TABLE child ENABLE constraint fk_parent  EXCEPTIONS INTO EXCEPTIONS; 


Error report:
SQL Error: ORA-02298: Kan (ROB.FK_PARENT) niet valideren - bovenliggende sleutels zijn niet gevonden.
02298. 00000 - "cannot validate (%s.%s) - parent keys not found"
*Cause:    an alter table validating constraint failed because the table has
           child records.
*Action:   Obvious

例外テーブルで問題を確認します。

select * from exceptions;

ROW_ID OWNER                          TABLE_NAME                     CONSTRAINT                   
------ ------------------------------ ------------------------------ ------------------------------
AABA78 ROB                            CHILD                          FK_PARENT                      
AAFAAA                                                                                              
Ow9AAC 

select  * from child where rowid = 'AABA78AAFAAAOw9AAC';

問題を解決する

delete from child where pk = 3;

1 rows deleted.

ALTER TABLE child ENABLE constraint fk_parent  EXCEPTIONS INTO EXCEPTIONS;

table CHILD altered.

制約が有効でデータが正しい

于 2012-09-20T11:14:33.283 に答える