2

複合キー(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が削除の問題を引き起こしていないことがわかります。

4

1 に答える 1

3

私の賭けは、問題は複合キーの存在とは何の関係もなく、インデックス付けされていない外部キーと関係があるということです。

質問から省略しない限りCITY、テーブルの列LOCATIONはインデックスに登録されません。つまり、から行を削除しようとするたびにCITY、Oracleはテーブルに対して全表スキャンを実行して、外部キー制約を適用するために孤立するLOCATION行を探す必要があります。LOCATION一般に、親から削除する場合は、子テーブルの外部キーにインデックスを付ける必要があります。したがって、とのLOCATION両方にインデックスを設定する必要があります。テーブルには、とのインデックスを設定する必要があります。CITYCOUNTRYCITYCOUNTRY(regionCountry, regionCode)

からのすべての行LOCATIONが削除された場合でも、Oracleがで全表スキャンを実行する必要がある場合はLOCATION、テーブルの最高水準点まで読み取る必要があります。以前にテーブルに250万行があり、を実行したDELETE場合でも、読み取る必要がありますが、から行を削除するたびに、これらの250万行を格納するために多くのブロックが必要でしたCITY

私の勘が正しいかどうかをいくつかの異なる方法でテストできます

  • CITYテーブル内の列にインデックスを付けることができLOCATIONます。
  • LOCATIONテーブルを参照する外部キー制約を削除できCITYます。
  • 行を削除する代わりにテーブルを切り捨てLOCATIONて、最高水準点をリセットし、テーブルスキャンにかかる時間を大幅に短縮することができます。
于 2012-10-18T21:50:45.550 に答える