我使用了 MySQLTuner,它指出一些表是碎片化的。我用了
mysqlcheck --optimize -A
优化所有表。它修复了一些表,但 MySQLTuner 仍然发现 19 个表碎片化。如何查看哪些表需要进行碎片整理?也许 OPTIMIZE TABLE 会在 mysqlcheck 没有的地方工作?或者我还应该尝试什么?
小智 46
简短的回答:
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;
Run Code Online (Sandbox Code Playgroud)
“你必须知道”的答案
首先你必须明白,当一行更新时,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;
Run Code Online (Sandbox Code Playgroud)
DATA_LENGTH 和 INDEX_LENGTH 是您的数据和索引正在使用的空间,DATA_FREE 是所有表页(分段)中未使用的总字节数。
这是一个真实的生产表的例子
| ENGINE | TABLE_NAME | data_length | index_length | data_free |
| InnoDB | comments | 896 | 316 | 5 |
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我们有一个使用 (896 + 316) = 1212 MB 的表,并且有 5 MB 的可用空间数据。这意味着“碎片率”为:
5/1212 = 0.0041
Run Code Online (Sandbox Code Playgroud)
...这是一个非常低的“碎片率”。
我一直在使用比率接近 0.2(意味着 20% 的空格)的表,并且从未注意到查询速度变慢,即使我优化了表,性能也是一样的。但是在 800MB 的表上应用优化表需要大量时间并阻塞该表几分钟,这在生产中是不切实际的。
因此,如果您考虑在性能方面的优势以及优化表所浪费的时间,我更喜欢 NOT OPTIMIZE。
如果您认为存储更好,请查看您的比率并查看优化时可以节省多少空间。它通常不会太多,所以我更喜欢不优化。
如果您进行优化,下一次更新将通过将页面分成两个或更多来创建空白空间。但是更新碎片表比更新未碎片表要快,因为如果表碎片化,则行上的更新不一定会拆分页面。
我希望这可以帮助你。
小智 19
只是添加到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;
Run Code Online (Sandbox Code Playgroud)
如果一个表被碎片化了一小部分(小于 5%?),那么你可以不理会它。
任何更大的东西,您都需要根据您的数据库使用情况、锁定表等来评估对表进行碎片整理的重要性。
优化表确实可以解决您遇到的问题。
如果您只有几个数据库,那么您可以使用 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();
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
70388 次 |
最近记录: |