InnoDB 테이블에서 공간 삭제 및 회수


14

700GB InnoDB 테이블이 있는데 더 이상 데이터를 쓰지 않습니다 (읽기 전용). 보유하고있는 오래된 데이터를 삭제하고 디스크 공간이 부족하기 때문에 해당 디스크 공간을 회수하고 싶습니다. auto-inc 기본 인덱스가 있기 때문에 삭제 부분은 매우 쉽습니다. 그것을 사용하여 청크를 반복하고 행을 삭제할 수는 있지만 공간을 다시 가져올 수는 없습니다. 나는 OPTIMIZE TABLE의지를 가정 하지만 700GB 테이블에서 영원히 걸릴 수 있으므로 간과하는 다른 옵션이 있습니까?

RolandoMySQLDBA에 의해 편집

테이블이이라고 가정하면 mydb.mytable다음 쿼리를 실행하고 여기에 게시하여 테이블 축소에 필요한 디스크 공간을 결정할 수 있습니다.

SELECT
    FORMAT(dat/POWER(1024,3),2) datsize,
    FORMAT(ndx/POWER(1024,3),2) ndxsize,
    FORMAT((dat+ndx)/POWER(1024,3),2) tblsize
FROM (SELECT data_length dat,index_length ndx
FROM information_schema.tables WHERE
table_schema='mydb' AND table_name='mytable') A;

허용되는 경우 테이블 구조도 확인해야합니다.

노암 편집

이것은 쿼리의 출력입니다.

datsize ndxsize tblsize 682.51
47.57 730.08

이것은 테이블 구조입니다 ( SHOW CREATE TABLE)

`CREATE TABLE `mybigtable` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `uid` int(11) NOT NULL,  
  `created_at` datetime NOT NULL,  
  `tid` bigint(20) NOT NULL,  
  `text` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL, 
  `ft` tinyint(1) NOT NULL,  
  `irtsd` bigint(20) NOT NULL,  
  `irtuid` int(11) NOT NULL,  
  `rc` int(11) NOT NULL,  
  `r` tinyint(1) NOT NULL,  
  `e` text CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,  `timezone` varchar(5) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `uid_tid` (`uid`,`tid`)) ENGINE=InnoDB AUTO_INCREMENT=2006963844 DEFAULT CHARSET=utf8`

데이터 만 캡처 할 다른 디스크 볼륨이 있습니까 ???
RolandoMySQLDBA

@RolandoMySQLDBA 마운트 할 수있는 외장 하드 드라이브가 있습니다. 그게 중요합니까?
Noam

@RolandoMySQLDBA 그러나 물론 700GB를 추가하지 않고도 일부 공간을 삭제하는 옵션과 같은 것
Noam

@RolandoMySQLDBA는 추가 디스크 크기로 인해 성능 문제가 발생합니까?
Aris

@ 디스크와 검색 시간에 따라 달라질 수 있습니다. 요즘, 대부분의 디스크는 이제 더 잘 작동하지만, 테이블에 디스크 공간이 큰 스파 스 포켓이 있다면 사이클을 낭비하는 것 (실제로 빠르게 진행되는 것)이 좋은가 ??? 이것은 일반적으로 16K 블록으로 고정되는 InnoDB의 경우에 특히 그렇습니다. 16K 블록의 내부 조각화를 사용하여 테이블을 조각 모음 할 수 있습니다 ALTER TABLE ... ENGINE=InnoDB;(빈 공간이있는 경우). 대부분은 매우 빠른 SSD에 만족하며 더 이상 걱정하지 않습니다.
RolandoMySQLDBA

답변:


21

좋은 질문입니다. 몇 가지 해결책이 있지만 테이블이 너무 커서 아무도 고통이 없습니다. :)

InnoDB 테이블을 "축소"하는 세 가지 솔루션이 있습니다.

1. 최적화 테이블

OPTIMIZE TABLE언급 한대로 사용할 수 있지만 innodb_file_per_table변수에 관심을 가져야 합니다.

mysql> show variables like "innodb_file_per_table";
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

설명하겠습니다 :

OPTIMIZE TABLE이노 테이블, 테이블 잠금 파크은 (결과가 수축 이유), 원래의 테이블을 삭제하고 원래 이름을 가진 새로운 테이블의 이름을 변경 새로운 깨끗한 테이블에있는 데이터를 복사한다. 그렇기 때문에 디스크의 테이블 볼륨을 두 배로 늘려야합니다 (작업 중에는 2x700GB 필요).

innodb_file_per_table = ON에있을 때 모든 테이블에는 적절한 데이터 파일이 있습니다. 따라서 OPTIMIZE명령문은 작업이 완료되면 새 데이터 파일 (~ 700GB)을 생성하고 MySQL은 원래 파일을 삭제하고 새 파일 이름을 바꿉니다 (따라서 700GB-데이터가 줄어들 기 때문에 더 적습니다) 작업 중에 생성 된 것은 해제됩니다)

innodb_file_per_table = OFF에있을 때 모든 데이터는 ibdata라는 하나의 데이터 파일로 갑니다 . 이 파일은 슬픈 특성을 가지고 있으며 축소 할 수 없습니다. 따라서 OPTIMIZE프로세스 중에 700GB 근처에 새 테이블이 생성되지만 삭제 및 이름 바꾸기 작업 (및 OPTIMIZE단계 종료 ) 후에도 ibdata 는 ~ 700GB를 릴리스하지 않으므로 일부 데이터를 원했지만 700GB가 있습니다. 더 멋진가요?

2. 테이블 변경

당신은 또한 ALTER TABLE문 을 사용할 수 있습니다 ALTER TABLE,와 같은 방식으로 작동합니다 OPTIMIZE TABLE. 당신은 단지 사용할 수 있습니다 :

ALTER TABLE myTable EGINE=InnoDB;

3. 테이블 변경 (온라인)

의 문제 OPTIMIZEALTER TABLE는 작동 중에 테이블을 잠기. Percona 도구 : pt-online-schema-change (Percona Toolkit : link )를 사용할 수 있습니다. pt-online-schema ...는 작업 중에 원본 테이블을 읽고 쓸 수있는 트리거 및 임시 테이블을 사용하여 메커니즘을 구성합니다. 나는이 도구를 프로덕션 환경 ALTER에서 꽤 멋지게 사용합니다.

FOREIGN KEY테이블, FK를 참조 해야 하며 혼란을 유발할 위험이 있습니다. 이 전제 조건을 확인하려면 다음을 쿼리하십시오.

mysql> SELECT COUNT(*) FROM information_schema.REFERENTIAL_CONSTRAINTS WHERE REFERENCED_TABLE_NAME = "myTable";
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.04 sec)

pt-online-schema-change를 사용하는 방법은 다음과 같습니다.

pt-online-schema-change --alter "ENGINE=InnoDB" D=myBase,t=myTable --user --ask-pass

innodb_file_per_table에 대한 나의 메모는이 솔루션에도 해당됩니다.

4. mysqldump

마지막 해결책은 덤프에서 모든 데이터베이스를 다시 작성하는 것입니다. 매우 길지만 매우 효율적입니다. ibdata 파일을 "축소"하는 유일한 솔루션입니다.

최대


또한 percona 도구 온라인 테이블 변경 옵션에서 700GB의 디스크 여유 공간이 필요합니까?
Noam

예, pt-online은 ALTER 온라인을 수행하기 위해 일부 메커니즘을 사용하지만 ALTER를 만듭니다.
Maxime Fouilleul

@MaximeFouilleul 추가 디스크 크기로 인해 성능 문제가 발생합니까?
Aris

1

디스크 크기가 부족하면 pt-online-schema-change (ONLINE)에서 제안한 Max와 동일하게 제안합니다. 나는 훨씬 작은 테이블 (200GB)로 같은 상황에 있었고 동시에 약간의 압축을 수행하기로 선택했습니다. 이 라인을 따라 뭔가 작동해야합니다.

pt-online-schema-change --alter="ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4" D=myBase,t=myTable --user --ask-pass

바라쿠다 파일 형식과 테이블의 COMPACT 형식 인 경우에만 작동합니다. 또한 innodb_file_per_table을 활성화해야합니다. 특히 텍스트가 많고 8K 또는 4K와 같은 더 작은 KEY_BLOCK_SIZE를 사용하는 경우 (테이블의 크기는 16K) 테이블 크기에 놀라운 영향을 줄 수 있습니다. 다른 블로그 에서이 문제와 관련하여 여러 벤치 마크에서 얻을 수있는 공간을 확인할 수도 있지만 MySQL 설명서는 25 ~ 50 %를 광고합니다 (거의 90 %였습니다).

이것은 MySQL 문서에서 SELECT를 수행 할 때 성능에 영향을 줄 수 있습니다.

따라서, 주어진 시간에, 버퍼 풀은 페이지의 압축 및 압축되지 않은 형식을 포함하거나 페이지의 압축 된 형식 만 포함하거나 둘 다 포함하지 않을 수 있습니다.

또한 MySQL은 버퍼 풀에 없을 때 데이터를 압축 해제해야합니다. 따라서 경고하십시오.

이것은 제 경우에는 실제로 잘 작동했습니다. 나는 긴 글을 썼다. 200GB는 26GB가되었습니다. 공연은 바뀌지 않았다.

자세한 정보는 다음 링크를 확인하십시오.

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-usage.html

https://dev.mysql.com/doc/refman/5.5/en/innodb-compression-internals.html

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.