MySQL 读取/写入每个表

Kat*_*kas 9 mysql optimization

我正在优化我们的数据库。本质上,我试图在我们的数据库中找到写入次数最多和读取次数最多的表。之后,我将把这些表符号链接到单独的驱动器中。

有没有办法跟踪每个表的活动?如下所示,每个表的 IOPS、写入、读取?

Aar*_*own 10

方法一

如果您使用的是Percona ServerMariaDB (>= 5.2),您可以简单地设置userstat/userstat_running变量来启用一堆新的 INFORMATION_SCHEMA 表,包括一个名为 TABLE_STATISTICS 的表,它提供了准确的信息。

例如:

mysql> SELECT TABLE_NAME, ROWS_READ, ROWS_CHANGED, ROWS_CHANGED_X_INDEXES FROM TABLE_STATISTICS ORDER BY ROWS_CHANGED DESC LIMIT 5;
+-------------------+------------+--------------+------------------------+
| TABLE_NAME        | ROWS_READ  | ROWS_CHANGED | ROWS_CHANGED_X_INDEXES |
+-------------------+------------+--------------+------------------------+
| user              |   21122527 |      5989231 |               23956924 |
| audit             |       1208 |      5020929 |               20083716 |
| sometemp          |   13995426 |      3182150 |                9546450 |
| creditcards       |    3566482 |      2998976 |               11995904 |
| order             | 2147483647 |      2662606 |               53252120 |
+-------------------+------------+--------------+------------------------+
Run Code Online (Sandbox Code Playgroud)

ROWS_CHANGED 将对应于写入最多的表,而 ROWS_READ 将对应于最多的读取。您还应该查看 INDEX_STATISTICS 以找到最常用和最不常用的索引。

另请参阅MariaDB 用户统计文档

方法二

如果您没有使用 Percona Server,您可以使用pt-query-digest来捕获您的查询样本,然后仅过滤掉 INSERT/UPDATE/DELETE。这看起来像这样:

mysql> SELECT @@GLOBAL.slow_query_log_file;
+------------------------------------------+
| @@GLOBAL.slow_query_log_file             |
+------------------------------------------+
| /var/logs/mysql/slowquery.log            |
+------------------------------------------+
1 row in set (0.00 sec)
mysql> SET GLOBAL slow_query_log_file='/tmp/allqueries.log';
mysql> SELECT @@GLOBAL.long_query_time;
+--------------------------+
| @@GLOBAL.long_query_time |
+--------------------------+
|                 0.250000 |
+--------------------------+
1 row in set (0.00 sec)
mysql> SET GLOBAL long_query_time = 0;
mysql> FLUSH LOGS;
mysql> SLEEP 600; SET GLOBAL long_query_time = 0.25; SET GLOBAL slow_query_log_file='/var/logs/mysql/slowquery.log'; FLUSH LOGS;
Run Code Online (Sandbox Code Playgroud)

现在你有一个文件, /tmp/allqueries.log其中包含在您的服务器上执行约 10 分钟的每个查询。

接下来,使用 pt-query-digest 对其进行分析以获取最常写入表的数据:

pt-query-digest /tmp/allqueries.log --group-by=distill --filter '$event->{arg} =~ m/^(update|delete|insert)/i' --limit 5 > /tmp/writes.txt
Run Code Online (Sandbox Code Playgroud)

如果您检查/tmp/writes.txt,您将看到靠近顶部的部分,如下所示:

# Profile
# Rank Query ID Response time Calls R/Call Apdx V/M   Item
# ==== ======== ============= ===== ====== ==== ===== ====================
#    1 0x        0.0558 26.8%   282 0.0002 1.00  0.00 INSERT UPDATE user
#    2 0x        0.0448 21.5%   246 0.0002 1.00  0.00 UPDATE audit
#    3 0x        0.0228 10.9%    11 0.0021 1.00  0.00 UPDATE sometemp
#    4 0x        0.0108  5.2%    16 0.0007 1.00  0.00 UPDATE creditcards
#    5 0x        0.0103  4.9%    43 0.0002 1.00  0.00 UPDATE order
Run Code Online (Sandbox Code Playgroud)

粗略地说,在您选择的示例期间,这些是您最多写入表格的内容。为了从表中获得最多的读取(大致),您可以将--filter参数更改为--filter '$event->{arg} =~ m/^select/i',您将看到类似的输出。

如果您只对写入感兴趣,您可以将二进制日志传入pt-query-digest并获得类似的结果:

mysqlbinlog mysql-bin.000511 | pt-query-digest --type=binlog --group-by=distill > /tmp/writes.txt
Run Code Online (Sandbox Code Playgroud)

您还可以使用 tcpdump 和 pt-query-digest --type=tcpdump

因此,话虽如此,假设您正在使用 InnoDB 表,我非常怀疑您是否会从这样做中获得很大的性能优势。由于数据被缓冲到 InnoDB 日志然后写入磁盘的方式,我不希望通过像这样移动单个表来获得太多或任何性能提升。您可能会看到将 InnoDB 日志文件本身移动到单独的、更快的磁盘以将日志读/写与表空间读/写分开的一些好处,但即使这样也是有问题的。投资具有电池备份缓存(或更好的 SSD)的快速、高质量 RAID 阵列将更好地利用您的资源。