문제

각 행에 무작위로 생성 된 기본 키, 메시지 및 사용자가있는 DB 테이블이 있습니다. 각 사용자에게는 약 10-100 개의 메시지가 있지만 10K-50K 사용자가 있습니다.

한 번에 각 사용자의 메시지를 매일 작성합니다. 새 사용자의 기존 메시지를 버리기 전에 테이블을 최대한 작게 유지하기 전에 각 사용자의 기존 메시지를 버리고 싶습니다.

지금 나는 이것을 효과적으로한다 :

delete from table where user='mk'

그런 다음 해당 사용자의 모든 메시지를 작성하십시오. 나는 이것을 동시에하는 스레드가 많기 때문에 많은 논쟁을보고 있습니다.

각 사용자에 대한 가장 최근의 메시지 세트를 유지 해야하는 추가 요구 사항이 있습니다.

DB에 직접 액세스 할 수 없습니다. 중고 피드백을 기반으로 문제를 추측하려고합니다. 이 시나리오에 집중하는 이유는 삭제 쿼리가 대기 시간이 많이 표시되기 때문입니다.

누구든지 조언을 제공 할 수 있습니까?

더 나을까요?

select key from table where user='mk'

그런 다음 거기에서 개별 행을 삭제 하시겠습니까? 나는 그것이 잔인한 잠금으로 이어질 수 있다고 생각합니다.

도움이 되었습니까?

해결책

아니요, 일련의 "행으로"(또는 Tom Kyte가 "Slow-By-Slow") 작업보다 일련의 행에 단일 SQL 문을 수행하는 것이 항상 좋습니다. 당신이 "많은 논쟁을보고있다"고 말할 때 정확히 무엇을보고 있습니까? 명백한 질문 : 열 사용자가 색인화되어 있습니까?

(물론, 열 이름은 예약 된 단어이기 때문에 Oracle 데이터베이스에서 실제로 사용자가 될 수는 없습니다!)

편집하다: 열 사용자가 색인화되지 않았다고 말했습니다. 즉, 각 삭제는 단지 10-100 행을 삭제하기 위해 최대 50k * 100 = 5 백만 행 (또는 최상의 10k * 10 = 100,000 행)의 전체 테이블 스캔이 포함되어 있음을 의미합니다. 사용자에 인덱스를 추가하면 문제가 해결 될 수 있습니다.

다른 팁

모든 사용자를 위해 매일이 작업을 수행한다면, 단일 문으로 테이블에서 모든 레코드를 삭제하지 않겠습니까? 또는

truncate table whatever reuse storage
/

편집하다

내가이 접근법을 제안하는 이유는 프로세스가 이전 메시지를 지우는 데있어서 매일의 사용자 메시지를 일일 배치 업로드처럼 보이기 때문입니다. 즉, 비즈니스 규칙은 "테이블은 주어진 사용자에게 하루의 메시지 만 보유 할 것입니다"라고 생각합니다. 이 프로세스가 모든 사용자에 대해 수행되면 단일 작업이 가장 효율적입니다.

그러나 사용자가 매일 새로운 메시지 세트를 얻지 못하면 그리고 각 사용자에 대한 최신 메시지 세트를 유지 해야하는 자회사 규칙이 있습니다.

자물쇠 경합을보고 있다고 확신하십니까? 너무 많은 동시성 (그러나 관련없는 업데이트)으로 인해 디스크 경합을보고있을 가능성이 더 높습니다. 이에 대한 해결책은 단순히 사용하는 스레드 수를 줄이는 것입니다. 디스크 경합이 적으면 총 처리량이 높아집니다.

요구 사항을 조금 더 명확하게 정의해야한다고 생각합니다 ...

예를 들어. 메시지를 작성하려는 모든 사용자를 알고 있으면 ID를 임시 테이블에 삽입하고 ID에 색인 및 배치 삭제를 색인화하십시오. 그런 다음 발사하는 실이 두 가지를 수행합니다. 사용자의 ID를 온도 테이블에 쓰고 다른 온도 테이블에 메시지를 씁니다. 그런 다음 스레드가 실행을 마치면 기본 스레드가

메시지에서 삭제 * 내부 join temp_members on id = temp_id

메시지에 삽입 * temp_messges에서 *를 선택하십시오

Oracle Syntax에 익숙하지는 않지만 사용자 메시지가 모두 빠르게 연속적으로 수행되면 접근하는 방법입니다.

도움이 되었기를 바랍니다

DBA와 대화하십시오

그는 당신을 돕기 위해 거기에 있습니다. 우리가 DBA가 개발자로부터 이와 같은 무언가에 대한 액세스를 할 때, 우리는 해당 작업에 대한 지원을 제공 할 것이라고 가정합니다. 코드가 완료하는 데 너무 오래 걸리고 해당 시간이 데이터베이스에 묶여있는 것처럼 보이면 DBA는 정확히 무슨 일이 일어나고 있는지 확인하고 제안을 제공하거나 아무것도 변경하지 않고 문제를 해결할 수 있습니다.

문제 진술을보고, 경합 문제를보고있는 것처럼 보이지는 않지만 기본 구조에 대해서는 아무것도 모릅니다.

실제로 DBA와 대화하십시오. 그는 아마도 최신 CPU 배포를 계획하는 대신 재미있는 것을 보는 것을 즐길 것입니다.

이것은 속도를 높일 수 있습니다.

조회 테이블 만들기 :

create table rowid_table (row_id ROWID ,user VARCHAR2(100));
create index rowid_table_ix1 on rowid_table (user);

야간 일자리를 실행하십시오 :

truncate table rowid_table;
insert /*+ append */ into rowid_table
select ROWID row_id , user
from table;
dbms_stats.gather_table_stats('SCHEMAOWNER','ROWID_TABLE');

그런 다음 기록을 삭제할 때 :

delete from table
where ROWID IN (select row_id
                from rowid_table
                where user = 'mk');

자신의 제안은 매우 합리적입니다. 작은 배치를 잠그는 것은 두 가지 장점이 있습니다.

  • 거래가 더 작을 것입니다
  • 잠금은 한 번에 몇 줄로 제한됩니다.

배치를 잠그는 것은 큰 개선이어야합니다.

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