2015-01-31 2 views
2

주 테이블에 150 만 행이있는 테이블 집합이 있습니다. 하위 클래스 중 하나가 1 백만 행에도 가깝습니다.많은 관계가있는 테이블에서 1 백만 행을 삭제하는 가장 좋은 방법

주 테이블의 데이터도 기록 테이블에 복사해야합니다. 먼저 하위 행과 하위 행을 삭제하는 PLSQL 스크립트를 작성했지만 프로세스가 너무 오래 걸리는 것으로 나타났습니다.

데이터를 삭제하기 위해 대량 수집을 사용하고 있습니다.

스크립트는 매주 월요일마다 Java 스케줄러에 의해 호출됩니다.

첫 번째 대량 삭제 (백만 행이 있음) 이후에 데이터베이스가 주당 30k 레지스터까지만 커지기 때문에 프로세스가 빨라질 것이라고 생각합니다.

이 문제를 해결하는 가장 좋은 해결책은 무엇입니까? 일반적으로

+0

테이블을 Table_Log, TableDetails_Log로 이름을 바꾸고 새로운 하나의 Table 및 TableDetails를 만들 수 없습니까? –

+0

처음 삭제할 때 그렇게 할 수 있지만 데이터를 삭제하는 절차는 반드시 실행해야합니다. 거대한 테이블 때문에 오래 걸릴 것입니다. 오래된 행을 삭제 한 후 1 시간 이내에 실행됩니다. 내가 원하는 것은이 문제에 가장 적합한 해결책을 사용하는 것이다. – br1337

+1

주간 이름 변경, Log20150121, Log20150128 ... 새 테이블을 만듭니다. 이 작업은 밀리 초 단위로 종료됩니다. –

답변

6

이 테이블에서 행을 많이 "삭제"하는 가장 빠른 방법은, 임시 테이블에 저장 테이블을 절단하는 것입니다 그들을 다시 삽입 :

create table tempt as 
    select * 
    from t 
    where . . .; 

truncate table t; 

insert into t 
    select * 
    from tempt; 

을이 한 테이블에서 작동 삭제를 계단식으로 처리하지 않습니다. 트리거 설정 방법에 따라 데이터가 변경 될 수 있습니다 (예 : 삽입 시간). 귀하의 질문은 충분한 정보를 제공하지 않습니다.

그러나, 이론적으로, 당신은 자식 테이블에이 과정을 계속할 수 :

create table tempchild as 
    select * 
    from child 
    where child.parentid in (select id from t); 

truncate table child; 

insert into child 
    select * 
    from tempchild; 

이 이것을 달성하기 위해 빠른 방법의 개요입니다. 다른 테이블의 레코드 간 관계에 영향을 줄 수있는 트리거 및 제약 조건이 있으면 더 복잡해집니다.

5

삭제하려는 테이블,이 테이블과 관련된 테이블 및 이러한 모든 테이블의 인덱스에 대한 설명없이 이러한 삭제가 왜 그렇게 오래 걸리는지 말할 수는 없습니다. 한 가지 생각 - 한 테이블에서 다른 테이블로 외래 키가있는 경우 외래 키 관계에 관련된 필드는 두 테이블 모두에서 인덱싱되어야합니다. 다음 인덱스를 생성해야한다이 경우

PARENT_TABLE (1,000,000 rows) 
    ID_PARENT  NUMBER PRIMARY KEY 
    SOMETHING  VARCHAR2(10) 
    SOMETHING_ELSE NUMBER 
    VALUE_FIELD  VARCHAR2(20) REFERENCES VALID_VALUES(VALUE_FIELD) 
    ID_XXX_TABLE NUMBER REFERENCES XXX_TABLE (ID_XXX_TABLE) 

CHILD_TABLE (2,000,000 rows) 
    ID_CHILD  NUMBER PRIMARY KEY 
    ID_PARENT  NUMBER REFERENCES PARENT_TABLE(ID_PARENT) CASCADE DELETES 
    BLAH   VARCHAR2(15) 
    BLAH_BLAH  VARCHAR2(100) 
    VALUE_FIELD  VARCHAR2(20) REFERENCES VALID_VALUES(VALUE_FIELD) 

XXX_TABLE (100,000 rows) 
    ID_XXX_TABLE NUMBER PRIMARY KEY 
    FUBAR   NUMBER 
    FOOBAR   NUMBER 
    VALUE_FIELD  VARCHAR2(20) REFERENCES VALID_VALUES(VALUE_FIELD) 

VALID_VALUES (25 rows) 
    VALUE_FIELD  VARCHAR2(20) PRIMARY KEY 
    GOOD_BAD_UGLY CHAR(1) CHECK(GOOD_BAD_UGLY IN ('G', 'B', 'U') 

: 예를 들어, 다음과 같은 테이블이 있다고 가정 해 보자 이러한 인덱스를 생성해야하는 이유

PK_PARENT_TABLE ON PARENT_TABLE (ID_PARENT) 
PARENT_TABLE_1 ON PARENT_TABLE (VALUE_FIELD) 
PARENT_TABLE_2 ON PARENT_TABLE (ID_XXX_TABLE) 

PK_CHILD_TABLE ON CHILD_TABLE (ID_CHILD) 
CHILD_TABLE_1 ON CHILD_TABLE (ID_PARENT) 
CHILD_TABLE_2 ON CHILD_TABLE (VALUE_FIELD) 

PK_XXX_TABLE ON XXX_TABLE (ID_XXX_TABLE) 
XXX_FIELD_1  ON XXX_TABLE (VALUE_FIELD) 

PK_VALID_VALUES ON VALID_VALUES (VALUE_FIELD) 

설명하기 위해,이 때 발생하는 생각 해보자 이러한 일부 테이블에서 행을 삭제하려면 :

PARENT_TABLE

DELETE FROM PARENT_TABLE WHERE ID_PARENT = 123 

이 작업이 실행되면 데이터베이스는 삭제할 행을 참조하는 모든 행을 찾아야합니다. CHILD_TABLE 인 PARENT_TABLE을 참조하는 외래 키 제약 조건이있는 테이블은 하나뿐입니다. 따라서 데이터베이스는 SELECT * FROM CHILD_TABLE WHERE ID_PARENT = 123에 해당하는 것을 실행해야합니다. 이제는이 문장을 항상 실행할 수 있습니다. 그러나 CHILD_TABLE.ID_PARENT가 색인되지 않으면 계획이 FULL TABLE SCAN이 될 것이라고 보장됩니다. CHILD_TABLE의 모든 행은으로 읽어야합니다. CHILD_TABLE에 행이 많은 경우 속도가 느려집니다.반면에, CHILD_TABLE에 ID_PARENT에 대한 인덱스가있는 경우에는 일반적으로 매우 빠른 직접 인덱스 조회가되어야합니다.

VALID_VALUES

DELETE FROM VALID_VALUES WHERE VALUE_FIELD = 'ZORTNOBBLE' 

은 아주 간단 같은데 - 단지에만 25 개 행이 VALID_VALUES에서 단일 행을 삭제합니다. 빨리해야 할거야, 그렇지? 흠 ... 그렇지 않을 수도 있습니다. VALID_VALUES.VALUE_FIELD를 참조하는 세 가지 외래 키 제약 조건이 있습니다. 참조하는 테이블 중 하나라도 VALUE_FIELD에 인덱스가 없으면 해당 테이블의 모든 행을 읽고 VALID_VALUES에서 삭제할 값이 있는지 확인해야합니다. 이것은 매우 느린 작업 일 가능성이 큽니다.

그래서 말했듯이, 외래 키 제약 조건의 양쪽에있는 테이블에는 각 외래 키의 모든 필드에 대한 인덱스가 있어야합니다. 귀하의 상황이 크게 향상 될 것입니다.

질문을 편집하고 모든 외래 키 제약 조건 및이 테이블에있는 모든 색인을 포함하여 관련된 테이블의 정의를 포함 할 수 있으면 누군가가보다 구체적인 조언을 제공 할 수 있습니다.

행운을 빈다.

0

몇 가지 테스트를 수행했는데 테이블 자체가 매우 느린 것으로 나타났습니다. 테스트중인 환경에서 인덱스를 삭제할 수는 없지만 인덱스가 성능 문제를 일으키고 있다고 생각합니다 (300 레코드를 삭제하는 데 18 초 걸렸습니다).

프로 시저에 시간 초과를 추가하여 테이블의 데이터를 삭제하는 데 하루에 4 시간 만 소비하므로 지금 당장 문제가 해결됩니다.

+0

스케줄러가 4 시간 동안 실행 중이며 매일 50 ~ 100k 레코드를 삭제하는 중입니다. – br1337

관련 문제