대용량 테이블의 대용량 데이터를 삭제하는 Mysql 최적화

3천만 개의 레코드가 있는 테이블이 있고 상태=1인 모든 레코드를 비즈니스를 중단하지 않고 삭제해야 한다고 가정하면 거의 600만 개의 레코드가 있습니다.

status=1인 tab_name에서 직접 삭제를 사용하면 이 문에 너무 많은 레코드가 포함되므로 잠금 대기 시간 초과 오류가 발생합니다.

1. 삭제, 자르기, 삭제의 차이점:

떨어지다

잘리다

삭제

구현 프로세스

DDL 문을 실행하면 전체 테이블과 테이블 구조는 물론 테이블 인덱스, 제약 조건, 트리거도 삭제됩니다.

DDL 문은 테이블 데이터만 삭제하며 테이블 구조, 인덱스, 제약 조건 등은 유지됩니다.

DML 문, 테이블의 데이터 삭제

롤백

캔트

캔트

할 수 있다

사무

트랜잭션이 없고, 테이블 잠금이 없으며, 로그 파일에 기록되는 대량의 로그가 없습니다.

table_name 테이블을 자른 후 즉시 디스크 공간을 해제하고 auto_increment 값을 재설정합니다.

트랜잭션은 로그에 기록되며 행 및 테이블 잠금이 있습니다.

삭제는 디스크 공간을 해제하지 않지만 후속 삽입은 이전에 삭제된 데이터를 덮어씁니다.

실행 효율성: 삭제 > 자르기 > 삭제

2. 일괄 한도 삭제 방식:

DELETE FROM tab_name WHERE status=1 ORDER BY status LIMIT 10000;

참고: 정렬 기준을 사용해야 하는 경우 정렬 기준 + 제한을 함께 사용해야 합니다. 그렇지 않으면 정렬 기준이 최적화 프로그램에 의해 최적화되어 의미가 없는 것으로 간주됩니다.

참고: 삭제 명령문이 인덱스에 없는 경우 먼저 기본 키를 찾은 다음 기본 키에 따라 데이터베이스를 삭제할 수 있습니다.

1) 한도 추가의 장점:

  1. 잘못된 SQL을 작성하는 비용을 줄이고, 500개 제한 등 잘못된 것을 삭제하더라도 500개의 데이터가 손실되므로 치명적이지 않으며, 해당 데이터는 binlog를 통해 빠르게 복구할 수 있습니다.
  2. 긴 트랜잭션을 피하기 위해 MySQL은 삭제 실행 시 관련된 모든 행에 쓰기 잠금 및 갭 잠금(gap locks)을 추가하고 DML 문 실행과 관련된 모든 행을 잠급니다. 삭제 횟수가 많으면 직접적인 영향을 미칩니다. 관련 사업의 사용 불가능.
  3. 삭제하는 데이터의 양이 많으면 한도를 추가하지 않고도 CPU를 채우기 쉬우므로 삭제 속도가 느려집니다.

위의 두 번째 사항은 statusid에 인덱스가 추가된다는 것이 전제인데, 우리 모두 알고 있듯이 잠금은 인덱스를 기반으로 이루어지며, statusid 필드가 인덱스되지 않으면 기본 키 인덱스로 스캔됩니다. statusid = 1인 레코드가 하나만 있으며 테이블도 잠깁니다.

2) 단일 삭제 및 업데이트 작업에는limit1을 사용하는 것이 확실히 좋은 습관입니다.

단일 업데이트 및 삭제 작업의 경우 SQL에 제한이 1이면 반환이 필요하고, 그렇지 않으면 반환 전에 전체 테이블 스캔이 수행됩니다. 효율성은 그 자체로 말해줍니다.

 3. 구성표 이름 바꾸기:

테이블에는 1억 6천만 개의 데이터와 자동 증가 ID가 있습니다. 최대값은 1억 6천만개인데 250만개가 넘는 데이터를 삭제해야 하는데 빨리 삭제하는 방법이 있나요?

해결책은 mysql 문서를 참조하십시오: http://dev.mysql.com/doc/refman/5.0/en/delete.html

큰 테이블에서 여러 행의 데이터를 삭제하면 innod 블록 테이블 크기 제한이 초과됩니다. 테이블 잠금 시간을 최소화하는 솔루션은 다음과 같습니다.

1) 삭제할 필요가 없는 데이터를 선택하여 동일한 구조의 빈 테이블에 저장한다.

INSERT INTO t_copy SELECT * FROM t WHERE ... ;

2) Rename Atomic 작업을 사용하여 원본 테이블과 복사 테이블의 이름을 바꿉니다.

RENAME TABLE t TO t_old, t_copy TO t;

3) 원본 테이블 삭제

DROP TABLE t_old;

4. 불필요한 인덱스 삭제 후 재구축

My SQL 데이터베이스를 사용하면 일부 테이블에는 하루에 약 300만 건에 달하는 상대적으로 많은 양의 데이터가 저장되는데, 이 테이블에는 3개의 인덱스가 설정되어 있는데, 이 인덱스는 다른 프로그램에서 꼭 필요한 인덱스이다. 이 테이블의 데이터는 오늘의 데이터만 유지하면 되므로, 다른 프로그램이 오전 특정 시점에 테이블의 데이터를 처리할 때마다 해당 테이블의 데이터를 어제와 전날의 데이터를 삭제해야 합니다. 10,000개의 레코드가 있을 경우 MySQL의 삭제 속도는 매우 느립니다. 10,000개의 레코드당 약 4분 정도 소요됩니다. 불필요한 데이터를 모두 삭제하려면 8시간 이상이 소요됩니다. , 이는 받아 들일 수 없습니다.

공식 MySQL 매뉴얼을 쿼리해 보면 데이터 삭제 속도는 생성된 인덱스 수에 정비례한다는 것을 알 수 있습니다(DML 작업의 경우 인덱스가 있으면 인덱스 정보가 업데이트되므로 속도가 느려집니다). 인덱스 2개를 테스트해서 찾았는데 이때 삭제속도가 꽤 빨라서 100만개 레코드에 1분 넘게 걸리더군요.. 그런데 이 2개 인덱스 모듈은 아직도 하루에 한번씩 데이터 정렬에 사용하고 있어서 그런 생각이 들었어요. 타협 방법:

  1. 데이터를 삭제하기 전에 이 두 인덱스를 삭제하세요. 이 작업은 3분 정도 걸립니다.
  2. 그런 다음 쓸모 없는 데이터를 삭제합니다. 이 프로세스는 2분도 채 걸리지 않습니다.
  3. 삭제가 완료된 후 인덱스를 다시 생성합니다. 현재 데이터베이스의 데이터는 레코드가 약 300,000~400,000개로 상대적으로 적고(이 테이블의 데이터는 시간당 약 100,000개 레코드씩 증가합니다) 인덱스 생성은 또한 약 10분 정도 매우 빠릅니다. 전체 삭제 과정은 약 15분 정도 소요됩니다. 이전 8시간에 비해 시간이 많이 절약됐다.

추천

출처blog.csdn.net/liuxiao723846/article/details/130360635