2017-12-20 29 views
2

약 93 백만 ml 레코드가있는 테이블을 업데이트해야합니다. DB는 5 초당 10k 레코드를 업데이트했으며, 이제는 약 60 백만 건의 업데이트 된 레코드 이후에 다음 10k 레코드를 업데이트합니다. 30-60 초가 걸리므로 null 인 열을 업데이트해야하는 이유는 모르겠다.
내가 커밋 각 10 개 K 레코드 루프 사용 : 많은 레코드가있는 Oracle DB의 업데이트 속도를 높입니다.

LOOP 
    UPDATE TABLE 
    SET DATE_COLUMN = v_hist_date 
    WHERE DATE_COLUMN IS NULL 
      AND ROWNUM <= c_commit_limit 
      AND NOT_REMOVED IS NULL; 

    EXIT WHEN SQL%ROWCOUNT = 0; 
    COMMIT; 
    END LOOP; 

당신이 너무 느리게 왜 어떤 아이디어가 어떻게이 업데이트를 빠르게 할 수 있습니까?

+0

예, PL/SQL 코드 – Krystian

+0

의 일부입니까? null 값을 가진 열이 있는데, 모두를 업데이트하면 Update가 0 행을 반환 할 때 종료됩니다. 예를 들어 작은 테이블에서 나를 처리했습니다. 1-2 mln 레코드를 사용하고 시간이 많이 걸리지는 않았지만 최신 db 버전도 있습니다. – Krystian

답변

5

업데이트도 쿼리입니다. 당신은 설명 계획을 게시하지 않았지만 당신이 당신의 진술이 전체 테이블 스캔을 실행하고있을 가능성이 높다고 생각되는 널 (NULL) 인 컬럼들을 필터링하고 있다면. 그것은 확실히 당신이 묘사하는 행동에 맞습니다.

어떻게 될까요? 첫 번째 루프는 FTS가 WHERE 조건에 거의 즉각적으로 맞는 10000 개의 행을 찾습니다. 그런 다음 루프를 종료하고 다시 시작하십시오. 이번에 FTS는 동일한 블록을 다시 읽습니다. 은 업데이트 할 수있는 다음 10000 개의 행을 찾기 전에 이전 반복에서 업데이트 한 블록을 포함하여입니다. 등등. 전체 테이블 스캔이 각 루프에 대해 더 많은 테이블을 읽어야하기 때문에 각 루프가 더 오래 걸립니다.

이것은 루프 내에서 무작위로 커밋하는 페널티 중 하나입니다. 지금은 너무 늦을 수도 있지만 더 나은 방법은 기본 키와 같은 색인 된 열을 추적하는 것입니다. 이러한 추적 키를 사용하면 이미 방문한 행을 지나치는 색인 스캔을 건너 뛸 수 있습니다.

+1

가장 좋은 방법은 현재 수행중인 일괄 업데이트가 아닌 단일 업데이트를 수행하여 UNDO 테이블 공간의 크기를 적절히 조정하는 것입니다. – Boneist

+1

@boneist - 나는 당신의 의견에 동의하지만이 같은 상황에서 "최선"을 정의하는 것은 어렵다고 생각합니다. 하나의 명령문에서 93m 행의 큰 덩어리를 업데이트 할 때의 문제는 넘어 질 위험이 있습니다. 그런 일이 생기면 우리는 모든 일을 잃어 버리고 다시해야만합니다. 더하기 측면에서 우리는 트랜잭션 무결성을 얻습니다. DEFAULT 값을 설정하는 것과 같은 다른 옵션이 있습니다 (다시 말하면 (지정되지 않은) 목적에 따라). – APC

+1

그래, 물론, 당신은 절대적으로 옳습니다! – Boneist