일부 테이블이 조각화되었음을 지적하는 MySQLTuner를 사용했습니다. 나는 사용했다
mysqlcheck --optimize -A
모든 테이블을 최적화합니다. 일부 테이블을 수정했지만 MySQLTuner는 여전히 19 개의 테이블을 조각화합니다. 조각 모음이 필요한 테이블을 어떻게 알 수 있습니까? 어쩌면 OPTIMIZE TABLE이 mysqlcheck가 작동하지 않은 곳에서 작동합니까? 아니면 다른 무엇을 시도해야합니까?
일부 테이블이 조각화되었음을 지적하는 MySQLTuner를 사용했습니다. 나는 사용했다
mysqlcheck --optimize -A
모든 테이블을 최적화합니다. 일부 테이블을 수정했지만 MySQLTuner는 여전히 19 개의 테이블을 조각화합니다. 조각 모음이 필요한 테이블을 어떻게 알 수 있습니까? 어쩌면 OPTIMIZE TABLE이 mysqlcheck가 작동하지 않은 곳에서 작동합니까? 아니면 다른 무엇을 시도해야합니까?
답변:
짧은 대답 :
select ENGINE, TABLE_NAME,Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free from information_schema.tables where DATA_FREE > 0;
"알아야합니다"답변
먼저 행이 업데이트 될 때 MySQL 테이블이 조각화된다는 것을 이해해야하므로 정상적인 상황입니다. 데이터가있는 덤프를 사용하여 가져온 테이블을 만들면 모든 행이 여러 고정 크기 페이지에서 조각화없이 저장됩니다. 가변 길이 행을 업데이트 할 때이 행을 포함하는 페이지는 변경 사항을 저장하기 위해 둘 이상의 페이지로 나뉘어지고 새 두 개 이상의 페이지에는 사용되지 않은 공간을 채우는 빈 공간이 포함됩니다.
물론 조각화가 너무 커지지 않는 한 성능에 영향을 미치지 않습니다. 조각화가 너무 많으면 원하는 쿼리를 보도록하겠습니다.
select ENGINE, TABLE_NAME,Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free from information_schema.tables where DATA_FREE > 0;
DATA_LENGTH 및 INDEX_LENGTH는 데이터 및 인덱스가 사용하는 공간이며 DATA_FREE는 모든 테이블 페이지에서 사용되지 않은 총 바이트 수입니다 (조각화).
실제 생산 테이블의 예는 다음과 같습니다.
| ENGINE | TABLE_NAME | data_length | index_length | data_free |
| InnoDB | comments | 896 | 316 | 5 |
이 경우 (896 + 316) = 1212MB를 사용하는 테이블이 있고 데이터의 여유 공간이 5MB입니다. 이것은 다음과 같은 "단편화 비율"을 의미합니다.
5/1212 = 0.0041
... "조각화 비율"이 정말 낮습니다.
0.2에 가까운 비율 (빈 공간의 20 %를 의미)로 테이블을 작업하고 있으며 테이블을 최적화하더라도 성능이 동일하더라도 쿼리 속도가 느려지지 않습니다. 그러나 800MB 테이블에 최적화 테이블을 적용하는 데 많은 시간이 걸리고 몇 분 동안 테이블을 차단하므로 프로덕션에서는 불가능합니다.
따라서 성능에서이기는 것을 고려하고 테이블을 최적화하는 데 낭비되는 시간을 고려하지 않으면 최적화하지 않는 것이 좋습니다.
스토리지에 더 적합하다고 생각되면 비율을 확인하고 최적화 할 때 절약 할 수있는 공간을 확인하십시오. 일반적으로 너무 많지 않으므로 최적화하지 않는 것이 좋습니다.
그리고 최적화하면 다음 업데이트에서 페이지를 둘 이상으로 분할하여 빈 공간을 만듭니다. 그러나 테이블이 조각난 경우 행에 대한 업데이트가 반드시 페이지를 분할하지는 않기 때문에 조각난 테이블보다 조각화 된 테이블을 업데이트하는 것이 더 빠릅니다.
이것이 도움이되기를 바랍니다.
Felipe-Rojas 의 답변에 추가하기 위해 쿼리의 일부로 조각 비율을 계산할 수 있습니다.
select ENGINE,
concat(TABLE_SCHEMA, '.', TABLE_NAME) as table_name,
round(DATA_LENGTH/1024/1024, 2) as data_length,
round(INDEX_LENGTH/1024/1024, 2) as index_length,
round(DATA_FREE/1024/1024, 2) as data_free,
(data_free/(index_length+data_length)) as frag_ratio
FROM information_schema.tables
WHERE DATA_FREE > 0
ORDER BY frag_ratio DESC;
테이블이 작은 비율 (5 % 미만)로 조각난 경우에는 그대로 두어도됩니다.
더 큰 것이면 테이블 사용량을 조각화하는 것이 얼마나 중요한지 DB 사용, 테이블 잠금 등을 기준으로 평가해야합니다.
테이블 최적화는 실제로 발생한 문제를 해결합니다.
데이터베이스가 몇 개인 경우 PHPMyAdmin을 사용하여 모든 데이터베이스를 살펴볼 수 있습니다. 오버 헤드가있는 테이블을 선택한 다음 최적화하도록 선택하십시오.
데이터베이스가 많으면 다른 방법이 바람직 할 것입니다.
나는 cron에서 다음 PHP 스크립트 설정을 사용하여 매 시간마다 실행합니다.
$DB = new mysqli ('localhost', 'DbUser', 'DbPassword');
$results = $DB->query('show databases');
$allDbs = array();
while ($row = $results->fetch_array(MYSQLI_NUM))
{
$allDbs[] = $row[0];
}
$results->close();
foreach ($allDbs as $dbName)
{
if ($dbName != 'information_schema' && $dbName != 'mysql')
{
$DB->select_db($dbName);
$results = $DB->query('SHOW TABLE STATUS WHERE Data_free > 0');
if ($results->num_rows > 0)
{
while ($row = $results->fetch_assoc())
{
$DB->query('optimize table ' . $row['Name']);
}
}
$results->close();
}
}
$DB->close();
mysqlcheck --optimize -A
SQL과 동일 하다고 확신한다OPTIMIZE TABLE <tablename>;
이 페이지를 방문하여 Felipe-Rojas와 sysadmiral의 쿼리가 매우 유용하다는 것을 알았습니다. 그러나 필자의 경우 WHM의 phpMyAdmin에서 쿼리를 실행하고 데이터베이스가 나열되지 않았기 때문에 TABLE_NAME 만 얻는 것이 도움이되지 않았으며 여러 데이터베이스의 테이블 이름이 동일합니다. 따라서 단순히 추가 TABLE_SCHEMA
하면 해당 열도 제공됩니다.
select ENGINE, TABLE_SCHEMA, TABLE_NAME, Round( DATA_LENGTH/1024/1024) as data_length , round(INDEX_LENGTH/1024/1024) as index_length, round(DATA_FREE/ 1024/1024) as data_free, (data_free/(index_length+data_length)) as frag_ratio from information_schema.tables where DATA_FREE > 0 order by frag_ratio desc
DB를 보여줍니다
ENGINE | TABLE_SCHEMA | TABLE_NAME | data_length | index_length | data_free | frag_ratio
InnoDB | db_name | db_table | 0 | 0 | 8 | 170.6667
"수정"하기 위해 phpMyAdmin에서 실행되는 "frag_ratio"가 높은 각 테이블에 대해 phpMyAdmin의 조각 모음 테이블 링크를 사용했습니다.
ALTER TABLE `table_name` ENGINE = InnoDB;
MySQL의 InnoDB 엔진을 사용하는 테이블은 기본적으로 반드시 그럴 필요는 없습니다 OPTIMIZEd
.
Data_free
from information_schema.tables
또는 from 값은 SHOW TABLE STATUS
0이 아닌 경우가 많습니다. 모든 작업을 완료했다고 생각하더라도 테이블 조각 모음을 수행 할 수 있습니다. 또한이 메트릭은 발생할 수 있고 발생할 수 있는 여러 조각 중 하나 일뿐 입니다. 또한 블록의 공간 낭비, 목록 실행 취소, 색인 BTree 대 데이터 BTree 등
그리고 innodb_file_per_table
의 사용을 복잡하게한다 Data_free
. 테이블이에 있으면 전체 테이블 스페이스 ibdata1
를 Data_free
나타냅니다. 다소 쓸모없는 숫자. 테이블이 자체 .ibd
파일에 있으면 테이블 크기의 몇 MB 또는 몇 퍼센트 중 큰 값일 수 있습니다.
당신이 삭제 한 경우에만 많은 행을 하고 테이블을 보충하지 않으려 수 그것은 가치가 실행 OPTIMIZE TABLE
.
PARTITIONs
또한 각 파티션은 일반적으로 4-7MB "사용 가능"을 나타 내기 Data_free
때문에 방해하는 양을 나타냅니다. 그리고 이것은 사라지지 않을 것입니다.
조각 모음이 필요한 이유
innodb_file_per_table=1
. 그러나 행을 추가하면 OS에서 다시 가져옵니다.Data_free
.역사 기록. 내가 주로 MyISAM 테이블을 사용하여 DBA를 도울 때, 아마도 매월 도움을받은 1000 개의 테이블 중 2 개를 발견했습니다 OPTIMIZE
. 그 이후로 수천 개의 InnoDB 테이블로 작업했지만 아직 도움이 될만한 성능 문제를 발견했습니다 OPTIMIZE
. (물론, OPTIMIZE
도움 이 될 수 있는 디스크 공간 문제가 있었지만 까다로워집니다. 일반적으로 DBA에는 실행할 디스크 공간이 충분하지 않습니다 OPTIMIZE
!)