複合キー(REGION)を持つ1つのテーブルと、そのテーブルを参照する別のテーブル(CITY)があります。挿入、クエリ、および個々の削除はすばやく機能します。問題は、sqlplusを使用してCITYの内容を一括削除しようとすると、CITYから削除すると、永久に時間がかかることです。このテーブルには最大400,000のエントリがあり、50,000のエントリを削除するだけで15〜20分かかります。Oracle11を使用したセットアップは次のとおりです。
create table COUNTRY
(
id varchar2(32) NOT NULL -- PK
...
);
create table REGION -- about 4000 entries
(
country varchar2(32) NOT NULL -- PK, FK to COUNTRY
regionCode char(2) NOT NULL -- PK
...
);
create table CITY -- about 400,000 entries
(
id number NOT NULL -- PK
country varchar2(32) NOT NULL -- FK to COUNTRY
regionCountry varchar2(32) NULL -- FK to REGION
regionCode char(2) NULL -- FK to REGION
...
);
create table LOCATION -- about 2,500,000 entries
(
id varchar2(32) NOT NULL -- PK
country varchar2(32) NOT NULL -- FK to COUNTRY
city number NULL -- FK to CITY
...
);
ALTER TABLE COUNTRY ADD CONSTRAINT PK_COUNTRY PRIMARY KEY (id) USING INDEX;
ALTER TABLE REGION ADD CONSTRAINT PK_REGION PRIMARY KEY (country, regionCode) USING INDEX;
ALTER TABLE CITY ADD CONSTRAINT PK_CITY PRIMARY KEY (id) USING INDEX;
ALTER TABLE IPGeoLoc ADD CONSTRAINT PK_LOCATION PRIMARY KEY (id) USING INDEX;
ALTER TABLE REGION ADD CONSTRAINT FK_REGION_COUNTRY
FOREIGN KEY (country) REFERENCES COUNTRY (id);
ALTER TABLE CITY ADD CONSTRAINT FK_CITY_COUNTRY
FOREIGN KEY (country) REFERENCES COUNTRY (id);
ALTER TABLE CITY ADD CONSTRAINT FK_CITY_REGION
FOREIGN KEY (regionCountry, regionCode) REFERENCES REGION (country, regionCode);
ALTER TABLE LOCATION ADD CONSTRAINT FK_LOCATION_COUNTRY
FOREIGN KEY (country) REFERENCES COUNTRY (id);
ALTER TABLE LOCATION ADD CONSTRAINT FK_LOCATION_CITY
FOREIGN KEY (city) REFERENCES CITY (id);
varchar2(32)フィールドはGUIDです。GUIDをPKとして使用するべきではないことはわかっていますが、これが問題であるという証拠がない限り、GUIDを変更することはできません。
LOCATIONからエントリを数秒で30万回、問題なく一括削除できるので、問題を引き起こしているのは複合キーであると私は信じています。
2番目の問題は、現在CITYテーブルに2つの国の列があることです。1つはCOUNTRYに直接リンクされており、もう1つはREGIONへの複合キーの一部としてリンクされています。コードでこれを行う方法を知っていて、国の列が1つしかないのですが、Hibernateを使用する必要があります。これは、削除の問題を除いてそのまま機能するため、これが問題を引き起こしていることを証明できない限り、変更することはできません。sqlplusを使用して削除を試みているので、Hibernateが削除の問題を引き起こしていないことがわかります。