문제

우리가 쿼리하는 일부를 제거에서 행 테이블에 기초한 id 필드(primary key).그것은 아주 간단한 쿼리:

delete all from OUR_TABLE where ID in (123, 345, ...)

문제입니다.의 id 거대할 수 있는(예를 들어.70k),그래서 쿼리 시간이 오래 걸립니다.방법은 없을 최적화하는 이?(우리가 사용하는 sybase-는 경우에는 사항).

도움이 되었습니까?

해결책

이것을 배치로 실행하는 것을 고려하십시오. 한 번에 1000 개의 레코드를 실행하는 루프는 모든 것을 수행하는 하나의 쿼리보다 훨씬 빠를 수 있으며 또한 다른 사용자에게 테이블을 잠그지 않아도됩니다.

캐스케이드 삭제 (및 많은 외국 키 테이블에 영향을받는) 또는 트리거가있는 경우 더 작은 배치로 실행해야 할 수도 있습니다. 당신은 당신의 상황에 가장 적합한 숫자인지 확인하기 위해 경험해야합니다. 나는 100의 배치로 삭제해야 할 테이블과 50000이 작동 한 다른 테이블을 가지고있었습니다 (이 경우에는 백만 레코드를 삭제할 때 운이 좋았습니다).

그러나 어떤 경우도 나는 임시 테이블을 삭제하고 거기에서 삭제하려는 키 값을 넣을 것입니다.

다른 팁

이와 같은 진술을하는 두 가지 방법이 있습니다.

  1. 새 테이블을 만들고 삭제할 행을 제외한 모든 행을 복사하십시오. 나중에 테이블을 교체합니다 (alter table name ...) 나는 어리석게 들릴 때도 시도해 볼 것을 제안합니다. 일부 데이터베이스는 삭제보다 복사 할 때 훨씬 빠릅니다.

  2. 테이블을 분할하십시오. n 테이블을 만들고보기를 사용하여 하나에 결합하십시오. 삭제 기준으로 그룹화 된 다른 테이블로 행을 정렬하십시오. 아이디어는 개별 행을 삭제하는 대신 전체 테이블을 떨어 뜨리는 것입니다.

70K 항목으로 IN 절을 구문 분석하는 것이 문제인지 궁금합니다. 대신 조인 된 임시 테이블을 사용해 보셨습니까?

할 수 있습 Sybase 처리 70K 인수에서 절?모든 데이터베이스와 함께 일했는 일부의 수에 대한 제한에 대해 인수 IN 절입니다.예를 들어,Oracle 제한 약 1000.

를 만들 수 있습니 select 에 대신에 절?을 단축시키는 sql.어쩌면을 도울 수 있는 대한의 큰 숫자 값에서는 절이 있습니다.무언가 이것을 좋아한다:

  DELETE FROM OUR_TABLE WHERE ID IN 
        (SELECT ID FROM somewhere WHERE some_condition)

삭제하는 많은 수의 레코드의 속도를 증가시킬 수 있습으로 일부 개입에 경우,데이터베이스 데이터베이스 모델을 수 있습니다.여기에 몇 가지 전략:

  1. 당신이 작업 속도를 높일 수 있습니다 떨어지는 인덱스 기록을 삭제하고 다시 인덱스 again.이를 제거하는 재조정 지수는 기록을 삭제.

    • 드롭다 모든 인덱스 테이블
    • 기록 삭제
    • 다시 인덱스
    • 가 많을 경우의 관계를 이 테이블,해제하려고 제약 확신하는 경우에는 삭제를 명령하지 않을 것이 어떤 무결성 제한 없음을 뜻합니다.삭제하는 것이기 때문에 빠르게 데이터베이스지 않을 확인 무결성이 있습니다.사용 제약 후 삭제합니다.
    • 용 무결성 제한조건을 확인하지 않도록 설정한 제약
    • 기록 삭제
    • 제약 조건 사용
    • 비활성화에 대한 트리거,테이블이 있는 경우와 귀하의 사업 규칙이 허용하는.레코드를 삭제,다음 사용 트리거합니다.

    • 마지막으로 하는 다른 건 복사본을 만들어 있는 테이블 포함되지 않는 행을 삭제한 다음,드롭 원래 이름을 복사하고 다시 무결성 제한조건이 있는 경우.

도록 노력하겠다 조의 1,2 및 3.을 작동하지 않는 경우,다음 4.면 모든 것은 천천히,나는 보이는 것이 더 큰 박스,더 많은 메모리 더 빠른 디스크가 있습니다.

성능을 사용하는 것이 무엇인지 알아보십시오!

많은 경우에 제공된 솔루션 중 하나를 사용할 수 있습니다. 그러나 다른 사람들이있을 수 있습니다 (Oracle 지식을 기반으로하는 다른 데이터베이스에서는 상황이 다를 수 있습니다. 편집 : Sybase를 언급 한 것을 보았습니다).

  • 그 테이블에 외국 키가 있습니까? 참조 ID가 색인화되어 있는지 확인하십시오
  • 그 테이블에 인덱스가 있습니까? 삭제하기 전에 떨어지고 삭제 후 재생성이 더 빠를 수 있습니다.
  • 실행 계획을 확인하십시오. 전체 테이블 스캔이 더 빠를 수있는 인덱스를 사용하고 있습니까? 아니면 다른 방법으로? 힌트가 도움이 될 수 있습니다
  • 위에 제안 된대로 새로 선택한 대신에 선택 테이블이 선택하는 대신 선택이 더 빠를 수 있습니다.

그러나 기억하십시오 : 먼저 성능을 사용하는 것이 무엇인지 알아보십시오.

DDL 문을 사용하는 경우 거래 및 백업에 대한 결과를 이해하고 수락해야합니다.

"in"으로 전달하는 ID를 테이블과 동일한 순서로 정렬하거나 인덱스가 저장됩니다. 그런 다음 디스크 캐시에서 더 많은 히트를 얻을 수 있습니다.

ID를 메인 테이블과 동일한 순서로 정렬 한 온도 테이블로 ID를 삭제하도록하면 데이터베이스가 메인 테이블 위에 간단한 스캔을하도록 할 수 있습니다.

데이터베이스 서버의 모든 CPU를 사용할 수 있도록 하나의 연결을 사용하고 연결을 통해 작업을 뱉어 낼 수 있지만 먼저 잠금 장치가 무엇인지 생각하십시오.

또한 온도 테이블이 최상의 솔루션이라고 생각합니다.

"ID에서 (id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id in id. 따라서 결합을 사용하여 삭제하는 것이 좋습니다. 많은 사람들이 그 기능에 대해 모릅니다.

따라서이 예제 테이블을 고려할 때 :

    -- set up tables for this example
    if exists (select id from sysobjects where name = 'OurTable' and type = 'U')
        drop table OurTable
    go

    create table OurTable (ID integer primary key not null)
    go
    insert into OurTable (ID) values (1)
    insert into OurTable (ID) values (2)
    insert into OurTable (ID) values (3)
    insert into OurTable (ID) values (4)
    go

그런 다음 다음과 같이 삭제 코드를 작성할 수 있습니다.

    create table #IDsToDelete (ID integer not null)
    go
    insert into #IDsToDelete (ID) values (2)
    insert into #IDsToDelete (ID) values (3)
    go
    -- ... etc ...
    -- Now do the delete - notice that we aren't using 'from'
    -- in the usual place for this delete
    delete OurTable from #IDsToDelete
       where OurTable.ID = #IDsToDelete.ID
    go
    drop table #IDsToDelete
    go
    -- This returns only items 1 and 4
    select * from OurTable order by ID
    go

our_table은 삭제 캐스케이드에 대한 참조가 있습니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top