InnoDB 테이블에서 조각화를 어떻게 제거합니까?


13

테이블 수가 많은 데이터베이스가 있습니다.

테이블에서 일부 레코드를 삭제하고 싶습니다. 레코드 수가 20K 또는 50K를 넘지 않는다고 말합니다.

모든 테이블은 InnoDB입니다. 그리고 file_per_table이다 떨어져 .

여러 테이블에서 레코드를 삭제하면 테이블에 조각화가 발생합니다.

조각화를 제거하는 방법이 있습니까?

4 월 17 일 업데이트

mysql> select TABLE_NAME, TABLE_SCHEMA, Data_free from information_schema.TABLES where TABLE_SCHEMA NOT IN ('information_schema', 'mysql') and Data_Free >0;
+-----------------+--------------+-----------+
| TABLE_NAME      | TABLE_SCHEMA | Data_free |
+-----------------+--------------+-----------+
| City            | world_innodb |   5242880 |
| City_Copy       | world_innodb |   5242880 |
| Country         | world_innodb |   5242880 |
| CountryLanguage | world_innodb |   5242880 |
| a               | world_innodb |   5242880 |
| t1              | world_innodb |   5242880 |
| t2              | world_innodb |   5242880 |
+-----------------+--------------+-----------+
7 rows in set (0.00 sec)

이제 내 질문은 내 테이블이 조각화되었는지 여부를 결정하는 방법입니다.



1
그리고 InnoDB 기사 : Percona의 블로그 사이트에서 조각화살펴보십시오 .
ypercubeᵀᴹ

답변:


14

2010 년 10 월 StackOverflow 에서이 문제를 해결했습니다. .

InnoDB 인프라에서 가장 바쁜 파일을 명심하십시오 : / var / lib / mysql / ibdata1

이 파일은 일반적으로 네 가지 유형의 정보를 저장합니다

  • 테이블 데이터
  • 테이블 인덱스
  • MVCC (Multiversioning Concurrency Control) 데이터
  • 테이블 메타 데이터 (테이블 스페이스 ID 목록)

OPTIMIZE TABLEibdata1에 저장된 InnoDB 테이블에 대해 실행 하면 두 가지 작업이 수행됩니다.

  • ibdata1 내에서 테이블의 데이터와 인덱스를 연속적으로 만들어서 더 빠르게 액세스
  • 연속 데이터 및 색인 페이지가 ibdata1에 추가되므로 ibdata1이 커집니다.

ibdata1에서 테이블 데이터와 테이블 인덱스를 분리하고 innodb_file_per_table을 사용하여 독립적으로 관리 할 수 ​​있지만 전체 디스크 공간 차이는 사라지지 않고 회수 할 수 없습니다. 더해야합니다.

ibdata1을 한 번만 축소 하려면 다음을 수행해야합니다.

1) MySQL 모든 데이터베이스를 SQL 텍스트 파일로 덤프합니다 (/root/SQLData.sql이라고 함).

2) 모든 데이터베이스를 삭제하십시오 (mysql 스키마 제외).

3) MySQL 종료

4) 다음 행을 /etc/my.cnf에 추가하십시오

[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G

참고 : innodb_buffer_pool_size에 대한 설정이 무엇이든, innodb_log_file_size가 innodb_buffer_pool_size의 25 %인지 확인하십시오.

5) ibdata1, ib_logfile0 및 ib_logfile1을 삭제하십시오.

이 시점에서 / var / lib / mysql에는 mysql 스키마 만 있어야합니다.

6) mysql을 다시 시작하십시오

이렇게하면 MySQL 버전에 따라 10MB 또는 18MB의 ibdata1, 1G의 ib_logfile0 및 ib_logfile1이 각각 다시 생성됩니다.

7) /root/SQLData.sql을 mysql로 ​​다시로드

ibdata1은 커지지 만 테이블 메타 데이터 만 포함합니다. 실제로, 그것은 수년에 걸쳐 매우 느리게 성장할 것입니다. ibdata1이 빠르게 성장하는 유일한 방법은 다음 중 하나 이상이있는 경우입니다.

  • DDL의 많은 ( CREATE TABLE, DROP TABLE, ALTER TABLE)
  • 많은 거래
  • 트랜잭션마다 커밋 할 많은 변경 사항

각 InnoDB 테이블은 ibdata1 외부에 존재합니다.

mydb.mytable이라는 InnoDB 테이블이 있다고 가정하십시오. / var / lib / mysql / mydb에 들어가면 테이블을 나타내는 두 개의 파일이 나타납니다.

  • mytable.frm (스토리지 엔진 헤더)
  • mytable.ibd (mydb.mytable의 테이블 데이터 및 테이블 인덱스 홈)

ibdata1은 더 이상 InnoDB 데이터 및 인덱스를 포함하지 않습니다.

/etc/my.cnf의 innodb_file_per_table 옵션을 사용하면 다음을 실행할 수 있습니다. OPTIMIZE TABLE mydb.mytable; /var/lib/mysql/mydb/mytable.ibd 파일이 실제로 축소됩니다.

나는 MySQL DBA로 경력에 여러 번이 일을했습니다

사실, 처음이 작업을 수행 할 때 50GB ibdata1 파일을 500MB로 축소했습니다.

시도 해봐. 이에 대한 추가 질문이 있으면 저에게 이메일을 보내십시오. 날 믿어. 이것은 단기적으로 그리고 장거리에서 작동합니다!

업데이트 2012-04-19 09:23 EDT

위 단계를 실행 한 후 조각 모음이 필요한 테이블을 어떻게 확인할 수 있습니까? 알아낼 수는 있지만 스크립트를 작성해야합니다.

예를 들면 다음과 같습니다 mydb.mytable. 테이블이 있다고 가정합니다 . innodb_file_per_table을 사용하면 /var/lib/mysql/mydb/mytable.ibd 파일이 있습니다.

두 개의 숫자를 검색해야합니다

OS에서 FILESIZE : 다음과 같이 OS에서 파일 크기를 확인할 수 있습니다

ls -l /var/lib/mysql/mydb/mytable.ibd | awk '{print $5}'

INFORMATION_SCHEMA에서 FILESIZE : information_schema.tables에서 다음과 같이 파일 크기를 확인할 수 있습니다.

SELECT (data_length+index_length) tblsize FROM information_schema.tables
WHERE table_schema='mydb' AND table_name='mytable';

OS 값에서 INFORMATION_SCHEMA 값을 빼고 그 차이를 INFORMATION_SCHEMA 값으로 나눕니다.

거기에서 해당 테이블을 조각 모음하는 데 필요한 백분율을 결정합니다. 물론 다음 명령 중 하나를 사용하여 조각 모음을 수행하십시오.

OPTIMIZE TABLE mydb.mytable;

또는

ALTER TABLE mydb.mytable ENGINE=InnoDB;

나는 생각하지 않는다는 / var / lib에 권장되는 innodb_file_per_table = 1 옵션을 사용하는 경우 / mysql을 /을 ibdata1은 매우 바쁜
CrackerJack9

1
@ CrackerJack9 ibdata1은 1) 이중 쓰기 버퍼 정보, 2) 2 차 색인을위한 버퍼 삽입, 3) 데이터 사전, 4) 롤백 세그먼트, 5) 테이블 스페이스 실행 취소로 인해 엄청나게 수월합니다. 이러한 것들을 그림으로 표현하려면 scribd.com/doc/31337494/XtraDB-InnoDB-internals-in-drawing 을 방문 하십시오 . InnoDB 테이블의 데이터 및 인덱스 페이지를 제거하더라도 높은 트랜잭션 환경에서 ibdata1은 여전히 ​​크게 증가 할 수 있습니다.
RolandoMySQLDBA

1
@ CrackerJack9 ibdata1에 대한 추가 활동을 논의하는 추가 게시물이 있습니다 : dba.stackexchange.com/a/23367/877
RolandoMySQLDBA

나는 그것이 여전히 그렇게 많이 사용되었다는 것을 깨닫지 못했습니다. 매우 감사히 생각한다!
CrackerJack9

@RolandoMySQLDBA 당신은 시간이있을 때 힙에 팝업 할 수 있습니까?
ypercubeᵀᴹ

5

행을 자주 삭제하거나 가변 길이 데이터 유형으로 행을 업데이트하는 경우 파일 시스템 조각화와 유사하게 데이터 파일에 많은 낭비되는 공간이 생길 수 있습니다.

사용하지 않는 경우 innodb_file_per_table옵션을 시간과 디스크를 많이 사용하는 절차 인 데이터베이스 내보내기 및 가져 오기만 수행 할 수 있습니다.

그러나를 사용 innodb_file_per_table하는 경우이 공간을 식별하고 회수 할 수 있습니다!

5.1.21 이전에는 여유 공간 카운터가 information_schema.tables의 table_comment 열에서 사용 가능합니다. 다음은 최소 100M (실제 97.65M)의 여유 공간이있는 테이블을 식별하는 SQL입니다.

information_schema.tables에서 table_schema, table_name, table_comment를 선택
하십시오. 'InnoDB'와 같은 엔진 및 table_comment와 같은 위치 : RLIKE 'InnoDB free : ([0-9] {6,}). *';

5.1.21부터는 data_free 열로 이동했습니다 (훨씬 더 적절한 위치).

info_schema.tables에서 data_free_MB AS table_schema, table_name, data_free / 1024 / 1024 선택 'InnoDB'와 같은 엔진 및 data_free> 100 * 1024 * 1024;

테이블을 재 구축하여 손실 된 공간을 회수 할 수 있습니다. 이를 수행하는 가장 좋은 방법은 실제로 변경하지 않고 'alter table'을 사용하는 것입니다.

ALTER TABLE `TableName` ENGINE=InnoDB;

InnoDB 테이블에서 '테이블 최적화'를 실행하면 MySQL이 배후에서 수행하는 작업입니다. 읽기 잠금이 발생하지만 전체 테이블 잠금은 발생하지 않습니다. 소요 시간은 테이블의 데이터 양 (데이터 파일의 크기는 아님)에 전적으로 의존합니다. 대량의 삭제 또는 업데이트가있는 테이블이있는 경우이 월 또는 매주 실행할 수 있습니다.


한 가지 더 나는 data_free> 100 * 1024 * 1024 .. 테이블이 조각화되었거나 조각화되지 않았다고 말할 수 있습니까?
압둘 마나프

내 업데이트 부분을 살펴보십시오.
압둘 마나프
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.