MySQL 通用查询日志

通用查询日志是mysqld所生成的记录。当客户端连接或断开时和从客户端接收到每个SQL语句时服务器会写信息到通用查询日志。当怀疑客户端有错误并且想了解客户端发送给mysqld的信息时通用查询日志非常有用。

当一个客户端连接时显示的每一行也包括using connection_type来指示建立连接的协议。connection_type是TCP/IP(不使用SSL的TCP/IP连接),SSL/TLS(使用SSL的TCP/IP连接),Socket(Unix socket file连接),Named Pipe(Windows命名管道连接),或Shared Memory(Windows共享内存连接)。

mysqld以它所接收到的语句顺序将它们写入通用查询日志,这可能不同于语句被执行的顺序。这个日志顺序与二进制日志顺序相反,语句会在执行之后但在任何锁被释放之前被写入通用查询日志。另外查询日志可能包含那些只查询数据但从没被写入二进制日志的语句。

当在一个复制主服务器上使用基于语句的二进制日志时,通过从服务器所接收到的语句会被写入每个从服务器的查询日志中。如果客户端使用mysqlbinlog工具读取事件并将它们传递给服务器,那么语句会被写入主服务器的查询日志中。

然而当使用基于行记录的二进制日志时,更新会被当作行改变被发送而不是SQL语句,并且当binlog_format为ROW时这些语句从来不会被写入查询日志。当这个变量设置为MIXED时依赖于语句的使用,指定的更新也可能不会被写入查询日志。

默认情况下,通用查询日志是被禁用的。为了显式指定初始化通用查询日志状态,使用–general_log[={0|1}]。没有参数或者参数为1,–general_log启用日志。当这个参数为0,这个选项将禁用日志。为了指定一个日志文件名,使用–general_log_file=file_name。为了指定日志目录,使用–log-output。

如果对通用查询日志文件没有指定文件名,默认名字为host_name.log。除非指定一个绝对路径来指定不同的目录否则服务器将在数据目录中创建日志文件名。

为了在运行时禁用或启用通用查询日志或改变日志文件名,使用全局general_log和general_log_file系统变量。设置general_log为0(或OFF)来禁用日志或1(或ON)来启用日志。设置general_log_file指定日志文件名。如果一个日志文件已经被opne,将会关闭它并打开新文件。

当通用查询日志被启用时,服务器将输出写入到由–log-output选项或log_output系统变量所指定的任何目录。如果启用日志,服务器将打开日志文件并将启动信息写入日志文件。然而除非FILE日志目录被选定否则更多的查询日志不会写入日志文件。如果日志目录为NONE,即使通用查询日志被启用服务器也不会将查询写入日志文件。如果日志目录值不包括FILE,设置日志文件名不会影响日志记录。

服务器重启和日志刷新不会导致生成新的通用查询日志文件(虽然刷新会关闭和重新打开日志文件)。为了重命名文件并创建新文件,使用以下命令:

shell> mv host_name.log host_name-old.log
shell> mysqladmin flush-logs
shell> mv host_name-old.log backup-directory

在Windows上,使用rename而不是mv

通过禁用日志也可以在运行时重命名通用查询日志

set global general_log='OFF';

当禁用日志后,在外部重命名日志文件,例如,通过命令行。然后再次启用日志:

set global general_log='ON';

这种方法可以在任何平台上工作并且不需要重启服务器。

对于当前连接会话级变量sql_log_off可以被设置为ON或OFF来启用或禁用通用查询日志。

写入通用查询日志的语句中的密码由服务器重写,不会以明文形式出现。密码重写对于通用查询日志来说是可以禁上的通过在服务器启动时使用–log-raw选项。这个选项对于诊断来说非常有用,为了查看服务器所接收到的精确语句文本,但由于安全原因不建议在生产环境中使用。

密码重写的一个含义是,不能被解析的语句(例如,由于语法错误)不会被写入通用查询日志,因为它们不能被认为是没有密码的。需要记录所有语句(包括有错误的语句)的用例应该使用——log-raw选项,记住这也可以绕过密码重写。

只有在预期使用纯文本密码时才会发生密码重写。对于具有期望密码散列值的语法的语句,不发生重写。如果为这种语法错误地提供了纯文本密码,则按给定的方式记录密码,而不进行重写。例如,如下所示记录下的语句,因为需要密码散列值

CREATE USER 'user1'@'localhost' IDENTIFIED BY PASSWORD 'not-so-secret';

log_timestamps系统变量控制首写入通用查询日志中信息的时区(对慢查询日志文件和错误日志也一样)。它不会影响写入日志表中的通用查询日志和慢查询日志信息的时区,但从这些表中检索行记录使用convert_tz()或设置会话变量time_zone系统变量可以将本地系统时区转换为任何你所期待的时区。

MySQL Slow Query log(慢查询日志)

慢查询日志由执行时间超过long_query_time秒且至少有min_examined_row_limit行被检查的SQL语句组成。long_query_time的最小值与默认值为0和10。它也可以指定为微秒。对于写入文件的日志,时间信息会被记录并且包含微秒部分。对于写入日志表的记录,只有整数时间被记录,微秒部分被忽略。

默认情况下,管理语句不会被记录,也不会记录不使用索引进行查询的语句。可以使用log_slow_admin_statements和log_queries_not_using_indexes来改变这种行为。

获取初始锁的时间不计算为执行时间。mysqld会在语句执行完成和所有锁被释放完成后将语句写入慢查询日志,因此日志顺序可能与语句的执行顺序不一致。

默认情况下,慢查询日志是被禁用的。为了显式指定初始化慢查询日志状态,使用–slow_query_log={0|1}。不使用参数值或参数值为1时,–slow_query_log启用日志。使用参数值为0时,禁用日志。为了指定慢查询日志文件名,使用–slow_query_log_file=file_name。为了指定日志目录,使用–log-output。

mysql> show variables like 'slow_query%';
+---------------------+-------------------------------------+
| Variable_name       | Value                               |
+---------------------+-------------------------------------+
| slow_query_log      | OFF                                 |
| slow_query_log_file | /mysqldata/mysql/localhost-slow.log |
+---------------------+-------------------------------------+
2 rows in set (0.01 sec)


mysql> show variables like 'log_output';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_output    | FILE  |
+---------------+-------+
1 row in set (0.01 sec)

如果没有为慢查询日志文件指定文件名,默认文件名为host_name-slow.log。除非使用绝对路私名指定不同的目录否则将在数据目录下创建默认文件。

为了禁用或启用慢查询日志或在运行时改变日志文件名,使用全局的slow_query_log和slow_query_log_file系统变量。设置slow_query_log为0(或OFF)来禁用日志,设置为1(或ON)来启用日志。设置slow_query_log_file来指定日志文件名。如果一个日志文件已经打开 ,它将关闭再打开新文件。

当慢查询日志被启用时,服务器将输出写入到由–log-output选项或log_output系统变量所指定的任何目录中。如果启用了日志,服务器打开日志文件并将启动信息写入文件中。然而,除非FILE日志目录被选择否则查询的进一步日志不会记录在文件中。如果目录为NONE,即使慢查询日志被启用也不会记录查询。如果日志目录不包含FILE,设置日志文件名不会影响日志功能。

如果使用–log-short-format选项,服务器会写少量信息到慢查询日志中。

为了在写入到慢查询日志中的语句中包含慢速管理语句,使用log_slow_admin_statements系统变量。管理语句包括alter table,
analyze table,check table,create index, drop index,optimizer table和repair table。

为了将不使用索引的语句写入慢查询日志中,可以启用log_queries_not_using_indexes系统变量。当这样的查询被写入时,慢查询日志可能增长很快。通过设置log_throttle_queries_not_using_indexes系统变量来对这些查询设置速率限制是有可能的。默认情况下,这个变量为0,这意味着没有限制。正值对不使用索引的查询的日志记录施加了每分钟的限制。第一个这样的查询打开一个60秒的窗口,在这个窗口内,服务器将查询记录到给定的限制,然后抑制其他查询。如果在窗口结束时存在被抑制的查询,服务器将记录一个摘要,指出有多少查询以及在这些查询中花费的累计时间。当服务器记录下一个不使用索引的查询时,下一个60秒窗口开始。

服务器按照以下顺序使用控制参数来决定是否向慢速查询日志写入查询:
1.查询必须不是管理语句或者log_slow_admin_statements必须被启用。
2.查询必须至少花了long_query_time所设定的秒数或者启用log_queries_not_using_indexes和没有使用索引的查询
3.查询必须至少检查了min_examined_row_limit所设置的行数。
4.根据log_throttle_queries_not_using_indexes设置必须不能被禁止。

log_timestamps系统变量控制着写入慢查询日志(通用查询日志和错误日志也一样)中信息所包含的时间戳中的时区信息。它不会影响写入通用查询日志和写入日志表中慢查询日志信息中的时区信息,但从这些日志表中检索数据通过使用convert_tz()或通过设置time_zone系统变量可以从本地系统时区转换成你所期待的任何时区。

所有日志行都包含一个时间戳。

服务器不会将由查询缓存处理的查询写入慢速查询日志,也不会将由于表只有零行或一行而无法从索引中获益的查询写入慢速查询日志。

默认情况下,复制从服务器不会将复制的查询写入慢速查询日志。为了改变这种行为,可以使用log_slow_slave_statements系统变量。

写入慢速查询日志的语句中的密码由服务器重写,不会以明文形式出现。

慢速查询日志可用于查找执行时间较长的查询,因此可以进行优化。然而,检查一个长的慢查询日志可能成为一项困难的任务。为了简化这一过程,可以使用mysqldumpslow命令处理一个慢速查询日志文件,以总结日志中出现的查询

MySQl 配置InnoDB持久化的优化器统计信息

配置InnoDB的优化器统计信息
介绍如何为InnoDB表配置持久化和非持久化的优化器统计信息。

持久性优化器统计数据将被持久保存可以跨跃服务器的重启,从而实现更大的计划稳定性和更一致的查询性能。持久性优化器统计数据还提供了控制和灵活性以及这些额外的好处:
.您可以使用innodb_stats_auto_recalc配置选项来控制是否在对表进行重大更改后自动更新统计信息

.您可以使用STATS_PERSISTENT、STATS_AUTO_RECALC和STATS_SAMPLE_PAGES子句以及CREATE TABLE和ALTER TABLE语句为单个表配置优化器统计信息

.您可以在mysql.innodb_table_stats和mysql.innodb_index_stats表中查询优化器的统计数据

mysql> select * from mysql.innodb_table_stats;
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    6
Current database: mysql

+---------------+-------------------+---------------------+--------+----------------------+--------------------------+
| database_name | table_name        | last_update         | n_rows | clustered_index_size | sum_of_other_index_sizes |
+---------------+-------------------+---------------------+--------+----------------------+--------------------------+
| cs            | address           | 2021-06-03 16:17:22 |      3 |                    1 |                        0 |
| cs            | articles          | 2021-01-12 16:39:07 |      2 |                    1 |                        0 |
| cs            | bit_test          | 2021-06-18 16:28:55 |      2 |                    1 |                        0 |
| cs            | individual        | 2021-05-27 17:20:38 |      8 |                    1 |                        0 |
| cs            | person            | 2021-06-03 16:13:47 |      2 |                    1 |                        0 |
| cs            | person1           | 2021-05-27 17:02:34 |      3 |                    1 |                        0 |
| cs            | rewrite_rules     | 2020-07-15 17:34:15 |      3 |                    1 |                        0 |
| cs            | sequence          | 2021-01-18 10:45:15 |      0 |                    1 |                        0 |
| cs            | t                 | 2021-09-13 22:27:49 |      0 |                    1 |                        0 |
| cs            | t1                | 2021-07-06 16:00:24 |      2 |                    1 |                        0 |
| cs            | test              | 2021-06-23 15:47:12 |      0 |                    1 |                        0 |
| cs            | test2             | 2021-06-23 15:57:48 |      2 |                    1 |                        0 |
| d1            | T1                | 2021-08-06 17:16:37 |      0 |                    1 |                        0 |
| d1            | child             | 2021-08-17 16:27:43 |      2 |                    1 |                        0 |
| d1            | t                 | 2021-08-17 17:30:55 |      0 |                    1 |                        0 |
| d1            | t1                | 2021-08-09 16:18:51 |      0 |                    1 |                        0 |
| mysql         | articles          | 2021-01-08 15:21:02 |      8 |                    1 |                        1 |
| mysql         | child             | 2021-03-01 11:39:44 |      0 |                    1 |                        1 |
| mysql         | client_firms#P#r0 | 2021-03-01 10:13:09 |      0 |                    1 |                        0 |
| mysql         | client_firms#P#r1 | 2021-03-01 10:13:09 |      0 |                    1 |                        0 |
| mysql         | client_firms#P#r2 | 2021-03-01 10:13:09 |      0 |                    1 |                        0 |
| mysql         | client_firms#P#r3 | 2021-03-01 10:13:09 |      0 |                    1 |                        0 |
| mysql         | count             | 2020-01-06 10:45:24 |      0 |                    1 |                        0 |
| mysql         | cs                | 2020-04-02 18:58:57 |      0 |                    1 |                        0 |
| mysql         | customer          | 2021-03-01 11:43:54 |      0 |                    1 |                        0 |
| mysql         | gtid_executed     | 2019-06-17 14:28:37 |      0 |                    1 |                        0 |
| mysql         | imptest           | 2019-10-28 11:47:04 |      2 |                    1 |                        0 |
| mysql         | jemp              | 2021-04-26 08:12:27 |      4 |                    1 |                        1 |
| mysql         | lc#P#p0           | 2021-03-01 10:20:18 |      0 |                    1 |                        0 |
| mysql         | lc#P#p1           | 2021-03-01 10:20:18 |      0 |                    1 |                        0 |
| mysql         | lc#P#p2           | 2021-03-01 10:20:18 |      0 |                    1 |                        0 |
| mysql         | lc#P#p3           | 2021-03-01 10:20:18 |      0 |                    1 |                        0 |
| mysql         | my_stopwords      | 2021-01-08 16:42:36 |      0 |                    1 |                        0 |
| mysql         | new_table         | 2021-01-13 16:53:36 |      0 |                    1 |                        0 |
| mysql         | opening_lines     | 2021-01-08 16:46:10 |      8 |                    1 |                        1 |
| mysql         | parent            | 2021-03-01 11:39:33 |      0 |                    1 |                        0 |
| mysql         | product           | 2021-03-01 11:43:50 |      0 |                    1 |                        0 |
| mysql         | product_order     | 2021-03-01 11:44:23 |      0 |                    1 |                        2 |
| mysql         | rc#P#p0           | 2021-02-26 11:21:58 |      0 |                    1 |                        0 |
| mysql         | rc#P#p1           | 2021-02-26 11:21:58 |      0 |                    1 |                        0 |
| mysql         | rc#P#p2           | 2021-02-26 11:21:58 |      0 |                    1 |                        0 |
| mysql         | rc#P#p3           | 2021-02-26 11:21:58 |      0 |                    1 |                        0 |
| mysql         | rc#P#p4           | 2021-02-26 11:21:58 |      0 |                    1 |                        0 |
| mysql         | sales             | 2021-01-20 17:00:50 |      0 |                    1 |                        0 |
| mysql         | t                 | 2021-04-26 15:37:14 |      0 |                    1 |                        0 |
| mysql         | t1                | 2021-04-26 11:04:17 |      0 |                    1 |                        0 |
| mysql         | t2                | 2021-04-26 11:05:46 |      0 |                    1 |                        0 |
| mysql         | t3                | 2021-04-26 11:05:58 |      0 |                    1 |                        0 |
| mysql         | t4                | 2021-04-26 11:11:41 |      0 |                    1 |                        0 |
| mysql         | t5                | 2020-10-10 16:24:57 |      0 |                    1 |                        0 |
| mysql         | test              | 2020-01-07 10:56:04 |      0 |                    1 |                        0 |
| mysql         | total             | 2021-02-19 15:22:54 |      0 |                    1 |                        0 |
| mysql         | triangle          | 2021-03-01 14:57:31 |      3 |                    1 |                        0 |
| query_rewrite | rewrite_rules     | 2020-07-15 16:36:38 |      3 |                    1 |                        0 |
| sys           | sys_config        | 2019-06-17 14:28:41 |      6 |                    1 |                        0 |
+---------------+-------------------+---------------------+--------+----------------------+--------------------------+
55 rows in set (0.04 sec)

mysql> select * from mysql.innodb_index_stats;
+---------------+-------------------+------------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name        | index_name       | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+-------------------+------------------+---------------------+--------------+------------+-------------+-----------------------------------+
| cs            | address           | PRIMARY          | 2021-06-03 16:17:22 | n_diff_pfx01 |          3 |           1 | address_id                        |
| cs            | address           | PRIMARY          | 2021-06-03 16:17:22 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | address           | PRIMARY          | 2021-06-03 16:17:22 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | articles          | GEN_CLUST_INDEX  | 2021-01-12 16:39:07 | n_diff_pfx01 |          2 |           1 | DB_ROW_ID                         |
| cs            | articles          | GEN_CLUST_INDEX  | 2021-01-12 16:39:07 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | articles          | GEN_CLUST_INDEX  | 2021-01-12 16:39:07 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | bit_test          | GEN_CLUST_INDEX  | 2021-06-18 16:28:55 | n_diff_pfx01 |          2 |           1 | DB_ROW_ID                         |
| cs            | bit_test          | GEN_CLUST_INDEX  | 2021-06-18 16:28:55 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | bit_test          | GEN_CLUST_INDEX  | 2021-06-18 16:28:55 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | individual        | PRIMARY          | 2021-05-27 17:20:38 | n_diff_pfx01 |          8 |           1 | individual_id                     |
| cs            | individual        | PRIMARY          | 2021-05-27 17:20:38 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | individual        | PRIMARY          | 2021-05-27 17:20:38 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | person            | PRIMARY          | 2021-06-03 16:13:47 | n_diff_pfx01 |          2 |           1 | person_id                         |
| cs            | person            | PRIMARY          | 2021-06-03 16:13:47 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | person            | PRIMARY          | 2021-06-03 16:13:47 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | person1           | PRIMARY          | 2021-05-27 17:02:34 | n_diff_pfx01 |          3 |           1 | person_id                         |
| cs            | person1           | PRIMARY          | 2021-05-27 17:02:34 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | person1           | PRIMARY          | 2021-05-27 17:02:34 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | rewrite_rules     | PRIMARY          | 2020-07-15 17:34:15 | n_diff_pfx01 |          3 |           1 | id                                |
| cs            | rewrite_rules     | PRIMARY          | 2020-07-15 17:34:15 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | rewrite_rules     | PRIMARY          | 2020-07-15 17:34:15 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | sequence          | GEN_CLUST_INDEX  | 2021-01-18 10:45:15 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| cs            | sequence          | GEN_CLUST_INDEX  | 2021-01-18 10:45:15 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | sequence          | GEN_CLUST_INDEX  | 2021-01-18 10:45:15 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | t                 | GEN_CLUST_INDEX  | 2021-09-13 22:27:49 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| cs            | t                 | GEN_CLUST_INDEX  | 2021-09-13 22:27:49 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | t                 | GEN_CLUST_INDEX  | 2021-09-13 22:27:49 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | t1                | GEN_CLUST_INDEX  | 2021-07-06 16:00:24 | n_diff_pfx01 |          2 |           1 | DB_ROW_ID                         |
| cs            | t1                | GEN_CLUST_INDEX  | 2021-07-06 16:00:24 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | t1                | GEN_CLUST_INDEX  | 2021-07-06 16:00:24 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | test              | PRIMARY          | 2021-06-23 15:47:12 | n_diff_pfx01 |          0 |           1 | id                                |
| cs            | test              | PRIMARY          | 2021-06-23 15:47:12 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | test              | PRIMARY          | 2021-06-23 15:47:12 | size         |          1 |        NULL | Number of pages in the index      |
| cs            | test2             | PRIMARY          | 2021-06-23 15:57:48 | n_diff_pfx01 |          1 |           1 | id                                |
| cs            | test2             | PRIMARY          | 2021-06-23 15:57:48 | n_diff_pfx02 |          2 |           1 | id,ts                             |
| cs            | test2             | PRIMARY          | 2021-06-23 15:57:48 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| cs            | test2             | PRIMARY          | 2021-06-23 15:57:48 | size         |          1 |        NULL | Number of pages in the index      |
| d1            | T1                | GEN_CLUST_INDEX  | 2021-08-06 17:16:37 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| d1            | T1                | GEN_CLUST_INDEX  | 2021-08-06 17:16:37 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| d1            | T1                | GEN_CLUST_INDEX  | 2021-08-06 17:16:37 | size         |          1 |        NULL | Number of pages in the index      |
| d1            | child             | PRIMARY          | 2021-08-17 16:27:43 | n_diff_pfx01 |          2 |           1 | id                                |
| d1            | child             | PRIMARY          | 2021-08-17 16:27:43 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| d1            | child             | PRIMARY          | 2021-08-17 16:27:43 | size         |          1 |        NULL | Number of pages in the index      |
| d1            | t                 | GEN_CLUST_INDEX  | 2021-08-17 17:30:55 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| d1            | t                 | GEN_CLUST_INDEX  | 2021-08-17 17:30:55 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| d1            | t                 | GEN_CLUST_INDEX  | 2021-08-17 17:30:55 | size         |          1 |        NULL | Number of pages in the index      |
| d1            | t1                | GEN_CLUST_INDEX  | 2021-08-09 16:18:51 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| d1            | t1                | GEN_CLUST_INDEX  | 2021-08-09 16:18:51 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| d1            | t1                | GEN_CLUST_INDEX  | 2021-08-09 16:18:51 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | articles          | FTS_DOC_ID_INDEX | 2021-01-08 15:21:02 | n_diff_pfx01 |          8 |           1 | FTS_DOC_ID                        |
| mysql         | articles          | FTS_DOC_ID_INDEX | 2021-01-08 15:21:02 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | articles          | FTS_DOC_ID_INDEX | 2021-01-08 15:21:02 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | articles          | PRIMARY          | 2021-01-08 15:21:02 | n_diff_pfx01 |          8 |           1 | id                                |
| mysql         | articles          | PRIMARY          | 2021-01-08 15:21:02 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | articles          | PRIMARY          | 2021-01-08 15:21:02 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | child             | GEN_CLUST_INDEX  | 2021-03-01 11:39:44 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | child             | GEN_CLUST_INDEX  | 2021-03-01 11:39:44 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | child             | GEN_CLUST_INDEX  | 2021-03-01 11:39:44 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | child             | par_ind          | 2021-03-01 11:39:44 | n_diff_pfx01 |          0 |           1 | parent_id                         |
| mysql         | child             | par_ind          | 2021-03-01 11:39:44 | n_diff_pfx02 |          0 |           1 | parent_id,DB_ROW_ID               |
| mysql         | child             | par_ind          | 2021-03-01 11:39:44 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | child             | par_ind          | 2021-03-01 11:39:44 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | client_firms#P#r0 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | client_firms#P#r0 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | client_firms#P#r0 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | client_firms#P#r1 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | client_firms#P#r1 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | client_firms#P#r1 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | client_firms#P#r2 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | client_firms#P#r2 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | client_firms#P#r2 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | client_firms#P#r3 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | client_firms#P#r3 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | client_firms#P#r3 | GEN_CLUST_INDEX  | 2021-03-01 10:13:09 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | count             | GEN_CLUST_INDEX  | 2020-01-06 10:45:24 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | count             | GEN_CLUST_INDEX  | 2020-01-06 10:45:24 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | count             | GEN_CLUST_INDEX  | 2020-01-06 10:45:24 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | cs                | GEN_CLUST_INDEX  | 2020-04-02 18:58:57 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | cs                | GEN_CLUST_INDEX  | 2020-04-02 18:58:57 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | cs                | GEN_CLUST_INDEX  | 2020-04-02 18:58:57 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | customer          | PRIMARY          | 2021-03-01 11:43:54 | n_diff_pfx01 |          0 |           1 | id                                |
| mysql         | customer          | PRIMARY          | 2021-03-01 11:43:54 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | customer          | PRIMARY          | 2021-03-01 11:43:54 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | gtid_executed     | PRIMARY          | 2019-06-17 14:28:37 | n_diff_pfx01 |          0 |           1 | source_uuid                       |
| mysql         | gtid_executed     | PRIMARY          | 2019-06-17 14:28:37 | n_diff_pfx02 |          0 |           1 | source_uuid,interval_start        |
| mysql         | gtid_executed     | PRIMARY          | 2019-06-17 14:28:37 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | gtid_executed     | PRIMARY          | 2019-06-17 14:28:37 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | imptest           | GEN_CLUST_INDEX  | 2019-10-28 11:47:04 | n_diff_pfx01 |          2 |           1 | DB_ROW_ID                         |
| mysql         | imptest           | GEN_CLUST_INDEX  | 2019-10-28 11:47:04 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | imptest           | GEN_CLUST_INDEX  | 2019-10-28 11:47:04 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | jemp              | GEN_CLUST_INDEX  | 2021-04-26 08:12:27 | n_diff_pfx01 |          4 |           1 | DB_ROW_ID                         |
| mysql         | jemp              | GEN_CLUST_INDEX  | 2021-04-26 08:12:27 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | jemp              | GEN_CLUST_INDEX  | 2021-04-26 08:12:27 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | jemp              | i                | 2021-04-26 08:12:27 | n_diff_pfx01 |          4 |           1 | g                                 |
| mysql         | jemp              | i                | 2021-04-26 08:12:27 | n_diff_pfx02 |          4 |           1 | g,DB_ROW_ID                       |
| mysql         | jemp              | i                | 2021-04-26 08:12:27 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | jemp              | i                | 2021-04-26 08:12:27 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | lc#P#p0           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | lc#P#p0           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | lc#P#p0           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | lc#P#p1           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | lc#P#p1           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | lc#P#p1           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | lc#P#p2           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | lc#P#p2           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | lc#P#p2           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | lc#P#p3           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | lc#P#p3           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | lc#P#p3           | GEN_CLUST_INDEX  | 2021-03-01 10:20:18 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | my_stopwords      | GEN_CLUST_INDEX  | 2021-01-08 16:42:36 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | my_stopwords      | GEN_CLUST_INDEX  | 2021-01-08 16:42:36 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | my_stopwords      | GEN_CLUST_INDEX  | 2021-01-08 16:42:36 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | new_table         | GEN_CLUST_INDEX  | 2021-01-13 16:53:36 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | new_table         | GEN_CLUST_INDEX  | 2021-01-13 16:53:36 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | new_table         | GEN_CLUST_INDEX  | 2021-01-13 16:53:36 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | opening_lines     | FTS_DOC_ID_INDEX | 2021-01-08 16:46:10 | n_diff_pfx01 |          8 |           1 | FTS_DOC_ID                        |
| mysql         | opening_lines     | FTS_DOC_ID_INDEX | 2021-01-08 16:46:10 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | opening_lines     | FTS_DOC_ID_INDEX | 2021-01-08 16:46:10 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | opening_lines     | PRIMARY          | 2021-01-08 16:46:10 | n_diff_pfx01 |          8 |           1 | id                                |
| mysql         | opening_lines     | PRIMARY          | 2021-01-08 16:46:10 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | opening_lines     | PRIMARY          | 2021-01-08 16:46:10 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | parent            | PRIMARY          | 2021-03-01 11:39:33 | n_diff_pfx01 |          0 |           1 | id                                |
| mysql         | parent            | PRIMARY          | 2021-03-01 11:39:33 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | parent            | PRIMARY          | 2021-03-01 11:39:33 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | product           | PRIMARY          | 2021-03-01 11:43:50 | n_diff_pfx01 |          0 |           1 | category                          |
| mysql         | product           | PRIMARY          | 2021-03-01 11:43:50 | n_diff_pfx02 |          0 |           1 | category,id                       |
| mysql         | product           | PRIMARY          | 2021-03-01 11:43:50 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | product           | PRIMARY          | 2021-03-01 11:43:50 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | product_order     | PRIMARY          | 2021-03-01 11:44:23 | n_diff_pfx01 |          0 |           1 | no                                |
| mysql         | product_order     | PRIMARY          | 2021-03-01 11:44:23 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | product_order     | PRIMARY          | 2021-03-01 11:44:23 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | product_order     | customer_id      | 2021-03-01 11:44:23 | n_diff_pfx01 |          0 |           1 | customer_id                       |
| mysql         | product_order     | customer_id      | 2021-03-01 11:44:23 | n_diff_pfx02 |          0 |           1 | customer_id,no                    |
| mysql         | product_order     | customer_id      | 2021-03-01 11:44:23 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | product_order     | customer_id      | 2021-03-01 11:44:23 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | product_order     | product_category | 2021-03-01 11:44:23 | n_diff_pfx01 |          0 |           1 | product_category                  |
| mysql         | product_order     | product_category | 2021-03-01 11:44:23 | n_diff_pfx02 |          0 |           1 | product_category,product_id       |
| mysql         | product_order     | product_category | 2021-03-01 11:44:23 | n_diff_pfx03 |          0 |           1 | product_category,product_id,no    |
| mysql         | product_order     | product_category | 2021-03-01 11:44:23 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | product_order     | product_category | 2021-03-01 11:44:23 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | rc#P#p0           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | rc#P#p0           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | rc#P#p0           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | rc#P#p1           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | rc#P#p1           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | rc#P#p1           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | rc#P#p2           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | rc#P#p2           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | rc#P#p2           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | rc#P#p3           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | rc#P#p3           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | rc#P#p3           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | rc#P#p4           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | rc#P#p4           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | rc#P#p4           | GEN_CLUST_INDEX  | 2021-02-26 11:21:58 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | sales             | GEN_CLUST_INDEX  | 2021-01-20 17:00:50 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | sales             | GEN_CLUST_INDEX  | 2021-01-20 17:00:50 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | sales             | GEN_CLUST_INDEX  | 2021-01-20 17:00:50 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | t                 | GEN_CLUST_INDEX  | 2021-04-26 15:37:14 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | t                 | GEN_CLUST_INDEX  | 2021-04-26 15:37:14 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | t                 | GEN_CLUST_INDEX  | 2021-04-26 15:37:14 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | t1                | PRIMARY          | 2021-04-26 11:04:17 | n_diff_pfx01 |          0 |           1 | c1                                |
| mysql         | t1                | PRIMARY          | 2021-04-26 11:04:17 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | t1                | PRIMARY          | 2021-04-26 11:04:17 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | t2                | PRIMARY          | 2021-04-26 11:05:46 | n_diff_pfx01 |          0 |           1 | c1                                |
| mysql         | t2                | PRIMARY          | 2021-04-26 11:05:46 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | t2                | PRIMARY          | 2021-04-26 11:05:46 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | t3                | PRIMARY          | 2021-04-26 11:05:58 | n_diff_pfx01 |          0 |           1 | c1                                |
| mysql         | t3                | PRIMARY          | 2021-04-26 11:05:58 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | t3                | PRIMARY          | 2021-04-26 11:05:58 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | t4                | PRIMARY          | 2021-04-26 11:11:41 | n_diff_pfx01 |          0 |           1 | c1                                |
| mysql         | t4                | PRIMARY          | 2021-04-26 11:11:41 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | t4                | PRIMARY          | 2021-04-26 11:11:41 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | t5                | GEN_CLUST_INDEX  | 2020-10-10 16:24:57 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | t5                | GEN_CLUST_INDEX  | 2020-10-10 16:24:57 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | t5                | GEN_CLUST_INDEX  | 2020-10-10 16:24:57 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | test              | GEN_CLUST_INDEX  | 2020-01-07 10:56:04 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | test              | GEN_CLUST_INDEX  | 2020-01-07 10:56:04 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | test              | GEN_CLUST_INDEX  | 2020-01-07 10:56:04 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | total             | GEN_CLUST_INDEX  | 2021-02-19 15:22:54 | n_diff_pfx01 |          0 |           1 | DB_ROW_ID                         |
| mysql         | total             | GEN_CLUST_INDEX  | 2021-02-19 15:22:54 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | total             | GEN_CLUST_INDEX  | 2021-02-19 15:22:54 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | triangle          | GEN_CLUST_INDEX  | 2021-03-01 14:57:31 | n_diff_pfx01 |          3 |           1 | DB_ROW_ID                         |
| mysql         | triangle          | GEN_CLUST_INDEX  | 2021-03-01 14:57:31 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | triangle          | GEN_CLUST_INDEX  | 2021-03-01 14:57:31 | size         |          1 |        NULL | Number of pages in the index      |
| query_rewrite | rewrite_rules     | PRIMARY          | 2020-07-15 16:36:38 | n_diff_pfx01 |          3 |           1 | id                                |
| query_rewrite | rewrite_rules     | PRIMARY          | 2020-07-15 16:36:38 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| query_rewrite | rewrite_rules     | PRIMARY          | 2020-07-15 16:36:38 | size         |          1 |        NULL | Number of pages in the index      |
| sys           | sys_config        | PRIMARY          | 2019-06-17 14:28:41 | n_diff_pfx01 |          6 |           1 | variable                          |
| sys           | sys_config        | PRIMARY          | 2019-06-17 14:28:41 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| sys           | sys_config        | PRIMARY          | 2019-06-17 14:28:41 | size         |          1 |        NULL | Number of pages in the index      |
+---------------+-------------------+------------------+---------------------+--------------+------------+-------------+-----------------------------------+
191 rows in set (0.00 sec)

.可以查看mysql.innodb_table_stats和mysql.innodb_index_stats表的last_update列查看统计信息最后一次更新的时间。

.您可以手动修改mysql.innodb_table_stats和mysql.innodb_index_stats表强制执行特定的查询优化计划或在不修改数据库的情况下测试可选计划。

默认情况下,持久化优化器统计特性是启用的(innodb_stats_persistent=ON)。

非持久优化器统计信息在每次服务器重启时和一些其他操作之后被清除,并在下一个表访问时重新计算。因此,在重新计算统计信息时可能会产生不同的估计,导致执行计划中的不同选择和查询性能的变化

本节还提供了有关估计ANALYZE TABLE复杂度的信息,这在试图在准确的统计数据和ANALYZE TABLE执行时间之间取得平衡时可能很有用。

配置持久优化器统计信息参数
持久性优化器统计信息特性将统计信息存储到磁盘,并在服务器重启时保持这些统计信息的持久性,从而提高了计划的稳定性,这样优化器就更有可能在每次给定查询时做出一致的选择。

当innodb_stats_persistent=ON或使用STATS_PERSISTENT=1创建或修改单个表时,优化器统计信息被持久化到磁盘。innodb_stats_persistent默认启用。

以前,在每次服务器重启和一些其他操作之后,都会清除优化器统计信息,并在下一个表访问时重新计算。因此,在重新计算统计信息时可能会产生不同的估计,导致查询执行计划中的不同选择,从而导致查询性能的变化。

持久性统计信息存储在mysql.innodb_table_stats和mysql.innodb_index_stats表中。

要恢复使用非持久优化器统计信息,可以使用ALTER TABLE tbl_name STATS_PERSISTENT=0语句修改表。

为持久优化器统计信息配置自动统计信息计算
innodb_stats_auto_recalc配置选项在默认情况下是启用的,它决定是否在表发生重大更改(超过10%的行)时自动计算统计数据。您还可以在CREATE TABLE或ALTER TABLE语句中使用STATS_AUTO_RECALC子句为单个表配置自动统计信息重新计算。innodb_stats_auto_recalc默认启用。

mysql> show variables like 'innodb_stats_auto_recalc';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_stats_auto_recalc | ON    |
+--------------------------+-------+
1 row in set (0.01 sec)

由于自动统计信息重新计算的异步特性(发生在后台),即使启用了innodb_stats_auto_recalc,当DML操作影响一个表的10%以上时,统计数据可能不会立即重新计算。在某些情况下,统计信息的重新计算可能会延迟几秒钟。如果在更改表的重要部分后需要立即更新统计信息,则运行analyze table来启动同步(前台)统计信息的重新计算。

如果innodb_stats_auto_recalc被禁用,那么在对索引的列进行大量更改之后,为每个适用的表发出ANALYZE TABLE语句,以确保优化器统计数据的准确性。您可以在将代表性数据加载到表中之后,在设置脚本中运行此语句,并在DML操作显著改变了索引列的内容之后定期运行它,或者在活动较少的时候调度运行它。当一个新的索引被添加到一个现有的表时,索引统计信息被计算并添加到innodb_index_stats表中,而不管innodb_stats_auto_recalc的值是多少。

要确保在创建新索引时收集统计信息,可以启用innodb_stats_auto_recalc选项,也可以在启用持久统计模式时,在创建每个新索引后运行ANALYZE TABLE。

为个别表配置优化器统计信息参数
innodb_stats_persistent,innodb_stats_auto_recalc和innodb_stats_persistent_sample_pages是全局配置选项。要覆盖这些系统范围的设置,并为各个表配置优化器统计信息参数,可以在CREATE TABLE或ALTER TABLE语句中定义STATS_PERSISTENT、STATS_AUTO_RECALC和STATS_SAMPLE_PAGES子句来实现。
.STATS_PERSISTENT指定InnoDB表是否启用持久化统计信息。默认值导致表的持久统计信息设置由innodb_stats_persistent配置选项决定。值1启用表的持久统计,而值0关闭此特性。在通过CREATE TABLE或ALTER TABLE语句启用持久统计信息后,在将代表性数据加载到表中之后,发出ANALYZE TABLE语句来计算统计信息

.STATS_AUTO_RECALC指定是否自动重新计算InnoDB表的持久统计信息。默认值导致表的持久统计信息设置由innodb_stats_auto_recalc配置选项决定。当表中10%的数据发生变化时,值1将导致重新计算统计数据。0可以防止对该表进行自动重新计算;使用此设置,在对表进行实质性更改后,发出一条ANALYZE TABLE语句来重新计算统计数据。

.STATS_SAMPLE_PAGES指定在估计索引列的基数和其他统计信息(例如由ANALYZE TABLE计算的统计信息)时要抽样的索引页数。

三个子句都在下面的CREATE TABLE示例中指定:

mysql> CREATE TABLE t1 (
    ->  id  int(8) NOT NULL auto_increment,
    ->  data  varchar(255),
    ->  date  datetime,
    -> PRIMARY KEY ( id ),
    -> INDEX  DATE_IX  ( date )
    -> ) ENGINE=InnoDB,
    -> STATS_PERSISTENT=1,
    -> STATS_AUTO_RECALC=1,
    -> STATS_SAMPLE_PAGES=25;
Query OK, 0 rows affected (0.09 sec)

配置InnoDB优化器统计信息的采样页面数
MySQL查询优化器使用关于键分布的估计统计信息,根据索引的相对选择性为执行计划选择索引。像ANALYZE TABLE这样的操作会导致InnoDB从表上的每个索引中随机取样页,以估计索引的基数。(这种技术被称为随机潜水。)

为了控制统计信息估计的质量(从而为查询优化器提供更好的信息),可以使用参数innodb_stats_persistent_sample_pages更改采样页面的数量,这个参数可以在运行时设置

Innodb_stats_persistent_sample_pages的默认值是20。作为一般指导原则,当遇到以下问题时,请考虑修改此参数:
1.统计数据不够准确,优化器会选择次优计划,如EXPLAIN输出所示。通过比较索引的实际基数(在索引列上运行SELECT DISTINCT返回)和mysql.innodb_index_stats持久化统计表提供的估计,可以检查统计信息的准确性。

如果确定统计信息不够准确,则应该增加innodb_stats_persistent_sample_pages的值,直到统计信息估计足够准确。然而,过多地增加innodb_stats_persistent_sample_pages可能会导致ANALYZE TABLE运行缓慢

2.ANALYZE TABLE太慢。在这种情况下,innodb_stats_persistent_sample_pages应该减少,直到ANALYZE TABLE的执行时间是可接受的。然而,过多地降低该值可能会导致第一个问题:不准确的统计数据和不够理想的查询执行计划

如果无法在精确的统计数据和ANALYZE TABLE执行时间之间取得平衡,那么可以考虑减少表中索引列的数量,或者限制分区的数量,以降低ANALYZE TABLE的复杂性。表主键中的列数也需要考虑,因为主键列被附加到每个非唯一索引。

在持久性统计信息计算中包括删除标记的记录
默认情况下,InnoDB在计算统计信息读取未提交的数据。在一个未提交事务从表中删除行的情况下,InnoDB在计算行估计和索引统计时,会排除被标记删除的记录,这可能会导致使用READ UNCOMMITTED以外的事务隔离级别并发操作表的其他事务的执行计划不是最优的。为了避免这种情况,可以启用innodb_stats_include_delete_marked,以确保在计算持久优化器统计数据时,InnoDB包含有标记删除的记录。

当innodb_stats_include_delete_marked被启用后,analyze table在计算统计信息时会考虑被标记为删除的记录。

innodb_stats_include_delete_marked是一个全局设置会影响所有的innodb表,并且它只应用于持久性优化器统计。

innodb_stats_include_delete_marked是在MySQL 5.7.16中引入的。

InnoDB持久化统计信息表
持久统计特性依赖于mysql数据库的内部管理表innodb_table_stats和innodb_index_stats。这些表在所有安装、升级和从源构建过程中自动设置。

mysql> desc innodb_table_stats;
+--------------------------+---------------------+------+-----+-------------------+-----------------------------+
| Field                    | Type                | Null | Key | Default           | Extra                       |
+--------------------------+---------------------+------+-----+-------------------+-----------------------------+
| database_name            | varchar(64)         | NO   | PRI | NULL              |                             |
| table_name               | varchar(199)        | NO   | PRI | NULL              |                             |
| last_update              | timestamp           | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| n_rows                   | bigint(20) unsigned | NO   |     | NULL              |                             |
| clustered_index_size     | bigint(20) unsigned | NO   |     | NULL              |                             |
| sum_of_other_index_sizes | bigint(20) unsigned | NO   |     | NULL              |                             |
+--------------------------+---------------------+------+-----+-------------------+-----------------------------+
6 rows in set (0.00 sec)



mysql> desc innodb_index_stats;
+------------------+---------------------+------+-----+-------------------+-----------------------------+
| Field            | Type                | Null | Key | Default           | Extra                       |
+------------------+---------------------+------+-----+-------------------+-----------------------------+
| database_name    | varchar(64)         | NO   | PRI | NULL              |                             |
| table_name       | varchar(199)        | NO   | PRI | NULL              |                             |
| index_name       | varchar(64)         | NO   | PRI | NULL              |                             |
| last_update      | timestamp           | NO   |     | CURRENT_TIMESTAMP | on update CURRENT_TIMESTAMP |
| stat_name        | varchar(64)         | NO   | PRI | NULL              |                             |
| stat_value       | bigint(20) unsigned | NO   |     | NULL              |                             |
| sample_size      | bigint(20) unsigned | YES  |     | NULL              |                             |
| stat_description | varchar(1024)       | NO   |     | NULL              |                             |
+------------------+---------------------+------+-----+-------------------+-----------------------------+
8 rows in set (0.00 sec)

innodb_table_stats和innodb_index_stats表都包含一个last_update列,显示InnoDB上次更新索引统计信息的时间,如下例所示:

mysql> select * from innodb_table_stats \G
*************************** 1. row ***************************
           database_name: cs
              table_name: address
             last_update: 2021-06-03 16:17:22
                  n_rows: 3
    clustered_index_size: 1
sum_of_other_index_sizes: 0

mysql> select * from innodb_index_stats where table_name='address' \G
*************************** 1. row ***************************
   database_name: cs
      table_name: address
      index_name: PRIMARY
     last_update: 2021-06-03 16:17:22
       stat_name: n_diff_pfx01
      stat_value: 3
     sample_size: 1
stat_description: address_id
*************************** 2. row ***************************
   database_name: cs
      table_name: address
      index_name: PRIMARY
     last_update: 2021-06-03 16:17:22
       stat_name: n_leaf_pages
      stat_value: 1
     sample_size: NULL
stat_description: Number of leaf pages in the index
*************************** 3. row ***************************
   database_name: cs
      table_name: address
      index_name: PRIMARY
     last_update: 2021-06-03 16:17:22
       stat_name: size
      stat_value: 1
     sample_size: NULL
stat_description: Number of pages in the index
3 rows in set (0.00 sec)

innodb_table_stats和innodb_index_stats是普通表,可以手动更新。手动更新统计信息的能力使得在不修改数据库的情况下强制执行特定的查询优化计划或测试备选计划成为可能。如果您手动更新统计信息,请执行FLUSH TABLE tbl_name命令让MySQL重新加载更新后的统计信息。

持久性统计信息被认为是本地信息,因为它们与服务器实例相关。因此,当自动统计信息重新计算发生时,innodb_table_stats和innodb_index_stats表不会被复制。如果您运行ANALYZE TABLE来启动统计信息的同步重新计算,那么这个语句将被复制(
除非您抑制了对它的日志记录),并在复制从服务器上进行重新计算。

InnoDB持久化统计信息表示例
innodb_table_stats表每个表包含一行。下面的例子演示了收集到的数据。

表t1包含一个主索引(列a、b)二级索引(列c、d)和唯一索引(列e、f):

mysql> CREATE TABLE t1 (
    -> a INT, b INT, c INT, d INT, e INT, f INT,
    -> PRIMARY KEY (a, b), KEY i1 (c, d), UNIQUE KEY i2uniq (e, f)
    -> ) ENGINE=INNODB;
Query OK, 0 rows affected (0.14 sec)

插入五行样本数据后,表如下所示:

mysql> insert into t1 values(1,1,10,11,100,101),(1,2,10,11,200,102),(1,3,10,11,100,103),(1,4,10,12,200,104),(1,5,10,12,100,105);
Query OK, 5 rows affected (0.12 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1;
+---+---+------+------+------+------+
| a | b | c    | d    | e    | f    |
+---+---+------+------+------+------+
| 1 | 1 |   10 |   11 |  100 |  101 |
| 1 | 2 |   10 |   11 |  200 |  102 |
| 1 | 3 |   10 |   11 |  100 |  103 |
| 1 | 4 |   10 |   12 |  200 |  104 |
| 1 | 5 |   10 |   12 |  100 |  105 |
+---+---+------+------+------+------+
5 rows in set (0.00 sec)

要立即更新统计信息,运行ANALYZE TABLE(如果启用了innodb_stats_auto_recalc,假设改变的表行达到10%的阈值,统计信息会在几秒钟内自动更新)

mysql> analyze table t1;
+----------+---------+----------+----------+
| Table    | Op      | Msg_type | Msg_text |
+----------+---------+----------+----------+
| mysql.t1 | analyze | status   | OK       |
+----------+---------+----------+----------+
1 row in set (0.03 sec)


mysql> select * from innodb_table_stats where table_name='t1' and database_name='mysql';
+---------------+------------+---------------------+--------+----------------------+--------------------------+
| database_name | table_name | last_update         | n_rows | clustered_index_size | sum_of_other_index_sizes |
+---------------+------------+---------------------+--------+----------------------+--------------------------+
| mysql         | t1         | 2022-02-17 14:52:13 |      5 |                    1 |                        2 |
+---------------+------------+---------------------+--------+----------------------+--------------------------+
1 row in set (0.01 sec)

表t1的表统计信息显示InnoDB最后更新表统计信息的时间为(2022-02-17 14:52:13),表中的行记录数为5,集簇索引大小为1个索引页,其它索引大小为2个索引页。

mysql> select * from innodb_table_stats where table_name='t1' and database_name='mysql' \G
*************************** 1. row ***************************
           database_name: mysql
              table_name: t1
             last_update: 2022-02-17 14:52:13
                  n_rows: 5
    clustered_index_size: 1
sum_of_other_index_sizes: 2
1 row in set (0.01 sec)

innodb_index_stats表包含每个索引的多行。innodb_index_stats表中的每一行都提供了与特定索引统计相关的数据,在stat_name列中显示命名,在stat_description列中显示描述。例如:

mysql> select * from innodb_index_stats where table_name='t1' and database_name='mysql';
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| database_name | table_name | index_name | last_update         | stat_name    | stat_value | sample_size | stat_description                  |
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
| mysql         | t1         | PRIMARY    | 2022-02-17 14:52:13 | n_diff_pfx01 |          1 |           1 | a                                 |
| mysql         | t1         | PRIMARY    | 2022-02-17 14:52:13 | n_diff_pfx02 |          5 |           1 | a,b                               |
| mysql         | t1         | PRIMARY    | 2022-02-17 14:52:13 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | t1         | PRIMARY    | 2022-02-17 14:52:13 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | t1         | i1         | 2022-02-17 14:52:13 | n_diff_pfx01 |          1 |           1 | c                                 |
| mysql         | t1         | i1         | 2022-02-17 14:52:13 | n_diff_pfx02 |          2 |           1 | c,d                               |
| mysql         | t1         | i1         | 2022-02-17 14:52:13 | n_diff_pfx03 |          2 |           1 | c,d,a                             |
| mysql         | t1         | i1         | 2022-02-17 14:52:13 | n_diff_pfx04 |          5 |           1 | c,d,a,b                           |
| mysql         | t1         | i1         | 2022-02-17 14:52:13 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | t1         | i1         | 2022-02-17 14:52:13 | size         |          1 |        NULL | Number of pages in the index      |
| mysql         | t1         | i2uniq     | 2022-02-17 14:52:13 | n_diff_pfx01 |          2 |           1 | e                                 |
| mysql         | t1         | i2uniq     | 2022-02-17 14:52:13 | n_diff_pfx02 |          5 |           1 | e,f                               |
| mysql         | t1         | i2uniq     | 2022-02-17 14:52:13 | n_leaf_pages |          1 |        NULL | Number of leaf pages in the index |
| mysql         | t1         | i2uniq     | 2022-02-17 14:52:13 | size         |          1 |        NULL | Number of pages in the index      |
+---------------+------------+------------+---------------------+--------------+------------+-------------+-----------------------------------+
14 rows in set (0.01 sec)

stat_name列显示了以下类型的统计信息:
.size: 当tat_name=size时, stat_value列显示索引中的总页数。

.n_leaf_pages: 当stat_name=n_leaf_pages时, stat_value列显示索引中叶页的数量。

.n_diff_pfxNN: 当stat_name=n_diff_pfx01时,stat_value列显示索引中第一列的distinct值的数量。当stat_name=n_diff_pfx02时,stat_value列显示索引中前两列的distinct值的数量。另外,stat_name=n_diff_pfxNN,stat_description列显示了被计数的索引列的逗号分隔列表。

为了进一步说明n_diff_pfxNN统计数据所提供的基数数据,考虑t1表示例。如下所示,用一个主索引(列a、b)、一个辅助索引(列c、d)和一个唯一索引(列e、f)创建了t1表。

mysql> CREATE TABLE t1 (
    -> a INT, b INT, c INT, d INT, e INT, f INT,
    -> PRIMARY KEY (a, b), KEY i1 (c, d), UNIQUE KEY i2uniq (e, f)
    -> ) ENGINE=INNODB;
Query OK, 0 rows affected (0.14 sec)


插入五行样本数据后,表如下所示:

mysql> insert into t1 values(1,1,10,11,100,101),(1,2,10,11,200,102),(1,3,10,11,100,103),(1,4,10,12,200,104),(1,5,10,12,100,105);
Query OK, 5 rows affected (0.12 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> commit;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1;
+---+---+------+------+------+------+
| a | b | c    | d    | e    | f    |
+---+---+------+------+------+------+
| 1 | 1 |   10 |   11 |  100 |  101 |
| 1 | 2 |   10 |   11 |  200 |  102 |
| 1 | 3 |   10 |   11 |  100 |  103 |
| 1 | 4 |   10 |   12 |  200 |  104 |
| 1 | 5 |   10 |   12 |  100 |  105 |
+---+---+------+------+------+------+
5 rows in set (0.00 sec)

当查询index_name,stat_name,stat_value和stat_description且where条件为stat_name like ‘n_diff%’,返回结果如下:

mysql> select index_name,stat_name,stat_value,stat_description from innodb_index_stats where table_name='t1' and
    -> database_name='mysql' and stat_name like 'n_diff%';
+------------+--------------+------------+------------------+
| index_name | stat_name    | stat_value | stat_description |
+------------+--------------+------------+------------------+
| PRIMARY    | n_diff_pfx01 |          1 | a                |
| PRIMARY    | n_diff_pfx02 |          5 | a,b              |
| i1         | n_diff_pfx01 |          1 | c                |
| i1         | n_diff_pfx02 |          2 | c,d              |
| i1         | n_diff_pfx03 |          2 | c,d,a            |
| i1         | n_diff_pfx04 |          5 | c,d,a,b          |
| i2uniq     | n_diff_pfx01 |          2 | e                |
| i2uniq     | n_diff_pfx02 |          5 | e,f              |
+------------+--------------+------------+------------------+
8 rows in set (0.00 sec)

对于primary索引,这里有两个n_diff%行。行数等于索引中的列数。

注意:对于非唯一索引 ,InnoDB会附加主键索引的列到非唯一索引中。

.当index_name=PRIMARY和stat_name=n_diff_pfx01时,stat_value值为1,这说明索引中第一个列(a)包含一个distinct值。列a的distinct值可以通过查看表t1中的列a的值来进行确认,只有单个distinct值1。计数列(a)显示在结果集的stat_description列中。

.当index_name=PRIMAY和stat_name=n_diff_pfx02时,stat_value值为5,这说明索引中前两列包含五个distinct值。列a和b的distinct值可以通过查看表t1中的列a和b的值来进行确认,有五个distinct值(1,1),(1,2),(1,3),(1,4),(1,5)。计数列(a,)显示在结果集的stat_description列中。

对于二级索引(i1),有4个n_diff%行。二级索引只定义了两个列(c,d),但是二级索引有四个n_diff%行,因为InnoDB将所有非唯一的索引都以主键作为后缀。因此,二级索引列(c,d)和主键列(a,b)有4个n_diff%行,而不是2个。
.当index_name=i1和stat_name=n_diff_pfx01时,stat_value的值为1,这说明索引中第一列(c)包含一个distinct值。列c的distinct值可以通过查看表t1中的列c的数据来进行确认。计数列c在stat_description列中显示。

.当index_name=i1和stat_name=n_diff_pfx02时,stat_value的值为2,这说明索引中前两列(c,d)包含两个distinct值。列c和d的distinct值可以通过查看表t1中的列c和d的数据来进行确认。计数列(c,d)在stat_description列中显示

.当index_name=i1和stat_name=n_diff_pfx03,stat_value的值为2,这说明索引中前三列(c,d,a)包含两个distinct值。列c,d和a的distinct值可以通过查看表t1中列c,d和a的数据来进行确认,有两个distinct值(10,11,1)和(10,12,1)。计数列(c,d,a)在stat_desciption列中显示

.当index_name=i1和stat_name=n_diff_pfx04,stat_value的值为5,这说明索引中四列(c,d,a,b)包含五个distinct值。列c,d,a和b的distinct值可以通过查看表t1中列c,d,a和b的数据来进行确认,有五个distinct值(10,11,1,1)和(10,11,1,2),(10,11,1,3),(10,12,1,4)和(10,12,1,5)。计数列(c,d,a,b)在stat_description列中显示

对于唯一索引(i2uniq),有两个n_diff%行。
.当index_name=i2uniq和stat_name=n_diff_pfx01时,stat_value值为2,这说明索引中第一列(e)包含两个distinct值。列e的distinct值可以通过查看表t1的列e的数据来进行确认,有两个distinct值(100)和(200)。计数列e在stat_description列中显示。

.当index_name=i2uniq和stat_name=n_diff_pfx02时,stat_value值为5,这说明索引中两列(e,f)包含五个distinct值。列e和f的distinct值可以通过查看表t1的列e和f的数据来进行确认,有五个distinct值(100,101),(200,102),(100,103),(200,104)和(100,105)。计数列(e,f)在stat_description列中显示。

使用innodb_index_stats表获取索引大小
表、分区或子分区的索引大小可以使用innodb_index_stats表来检索。在下面的例子中,检索表t1的索引大小。

mysql> select sum(stat_value) pages,index_name,sum(stat_value)*@@innodb_page_size size
    -> from mysql.innodb_index_stats where table_name='t1' and database_name='mysql' and stat_name='size' group by index_name;

+-------+------------+-------+
| pages | index_name | size  |
+-------+------------+-------+
|     1 | PRIMARY    | 16384 |
|     1 | i1         | 16384 |
|     1 | i2uniq     | 16384 |
+-------+------------+-------+
3 rows in set (0.04 sec)

mysql> show variables like 'innodb_page_size';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| innodb_page_size | 16384 |
+------------------+-------+
1 row in set (0.01 sec)

对于分区或子分区,可以使用带有修改后的WHERE子句的相同查询来检索索引大小。例如,下面的查询检索表t1的分区的索引大小

mysql> select sum(stat_value) pages,index_name,sum(stat_value)*@@innodb_page_size size
    -> from mysql.innodb_index_stats where table_name like't1#P%' and database_name='mysql' and stat_name='size' group by index_name;
Empty set (0.01 sec)

MySQL 配置InnoDB清理调度

配置InnoDB清理调度
InnoDB自动执行的清除操作(一种垃圾收集)可以由一个或多个独立的线程执行,而不是作为主线程的一部分。使用独立线程可以使主数据库操作独立于后台的维护工作运行,从而提高了可伸缩性。

要控制这个特性,请增加配置选项innodb_purge_threads的值。如果DML操作集中在一个或几个表上,请将设置设置得低一些,这样线程就不会为了访问繁忙的表而相互竞争。如果DML操作分布在多个表中,则增加设置。它的最大值是32。Innodb_purge_threads是非动态配置选项,这意味着它不能在运行时配置。

还有一个相关的配置选项,innodb_purge_batch_size,默认值为300,最大值为5000。此选项主要用于清洗操作的试验和调优,一般用户不应该对此感兴趣。

MySQL 配置自旋锁轮询

配置自旋锁轮询
很多InnoDB的互斥锁和rw-lock会被预留一段时间。在多核系统上,线程在睡觉前持续检查它是否可以获得互斥锁或rw-lock,这样会更有效率。如果互斥锁或rw-lock在此轮询期间可用,线程可以立即在同一时间片中继续运行。然而,由共享对象的多个线程进行过于频繁的轮询会导致缓存乒乓现象,不同的处理器会使彼此缓存的部分失效。InnoDB通过在两次轮询之间随机等待时间来最小化这个问题。延迟被实现为一个忙碌的循环。

您可以使用参数innodb_spin_wait_delay来控制测试互斥锁或rw-lock之间的最大延迟。延迟循环的持续时间取决于C编译器和目标处理器。(在100MHz奔腾时代,延迟单位是一微秒。)在所有处理器核心共享高速缓存内存的系统中,可以通过设置innodb_spin_wait_delay=0来减少最大延迟或禁用繁忙循环。在具有多个处理器芯片的系统上,缓存失效的影响可能更加显著,您可能会增加最大延迟。

innodb_spin_wait_delay默认值为6。自旋等待延迟是一个动态的、全局的参数,你可以在MySQL选项文件(my.cnf或my.ini)中指定,或者在运行时使用SET global innodb_spin_wait_delay=delay命令来更改,其中delay是所需的最大延迟。更改设置需要超级权限。

MySQL 配置InnoDB主线程I/O速率

配置InnoDB主线程I/O速率
InnoDB中的主线程是在后台执行各种任务的线程。这些任务大多数都与I/O相关,比如从缓冲池刷新脏页,或者将更改从插入缓冲区写入适当的二级索引。主线程试图以不影响服务器正常工作的方式执行这些任务。它试图估计可用的空闲I/O带宽,并调整其活动以利用这些空闲容量。从历史上看,InnoDB已经使用了硬编码值 100 IOPs(每秒输入/输出操作数)作为服务器的总I/O容量。

innodb_io_capacity表示InnoDB可用的总I/O容量。该参数应该设置为系统每秒可以执行的I/O操作数。该值取决于您的系统配置。当设置innodb_io_capacity时,主线程会根据设置的值来估算后台任务可用的I/O带宽。将该值设置为100将恢复到原来的行为。

innodb_io_capacity可以设置为100或更大的任意值。默认值是200,这反映了典型的现代I/O设备的性能要高于早期的MySQL。通常,前面的默认值100左右的值适合消费者级存储设备,比如高达7200 rpm的硬盘驱动器。更快的硬盘驱动器、RAID配置和ssd受益于更高的值。

innodb_io_capacity设置是所有缓冲池实例的总限制。当脏页被刷新时,innodb_io_capacity限制将在缓冲池实例中平均分配。更多信息请参见innodb_io_capacity系统变量描述。

您可以在MySQL选项文件(my.cnf或my.ini)中设置该参数的值,或者使用set GLOBAL命令动态更改它,该命令需要超级权限

innodb_flush_sync配置选项会导致innodb_io_capacity设置在检查点发生I/O突发时被忽略。Innodb_flush_sync默认开启。

以前,InnoDB主线程还执行任何需要的清除操作。在MySQL 5.6.5及以上版本中,这些I/O操作被转移到其他后台线程,其数量由innodb_purge_threads配置选项控制。

MySQL 配置后台InnoDB I/O线程数

配置后台InnoDB I/O线程数
InnoDB使用后台线程来处理各种类型的I/O请求。您可以使用innodb_read_io_threads和innodb_write_io_threads配置参数来配置服务于数据页读写I/O的后台线程数。这些参数分别表示用于读和写请求的后台线程数。它们在所有支持的平台上都是有效的。你可以在MySQL选项文件(my.cnf或my.ini)中设置这些参数的值;不能动态地更改值。这些参数的默认值是4,允许的值范围是1-64。

这些配置选项的目的是让InnoDB在高端系统上更具扩展性。每个后台线程最多可以处理256个I/O请求。后台I/O的一个主要来源是预读请求。InnoDB试图平衡传入请求的负载,使得大多数后台线程都能平等地工作。InnoDB也尝试将读请求从相同的extent分配到相同的thread,以增加合并请求的机会。如果你有一个高端的I/O子系统,你在SHOW ENGINE INNODB STATUS输出中看到超过64个innodb_read_io_threads挂起的读请求,你可以通过增加innodb_read_io_threads的值来提高性能。

在Linux系统上,InnoDB默认使用异步I/O子系统来执行数据文件页面的预读和写请求,这改变了InnoDB后台线程服务这些类型的I/O请求的方式。

在Linux上使用异步I/O
InnoDB使用Linux上的异步I/O子系统(原生AIO)来执行数据文件页面的预读和写请求。这种行为由innodb_use_native_aio配置选项控制,该选项只适用于Linux系统,默认情况下是启用的。在其他类unix系统上,InnoDB只使用同步I/O。过去,InnoDB只在Windows系统上使用异步I/O。在Linux上使用异步I/O子系统需要libaio库。

使用同步I/O,查询线程会对I/O请求进行排队,而InnoDB后台线程每次会检索一个排队的请求,并对每个请求发出同步I/O调用。当一个I/O请求完成并且I/O调用返回时,InnoDB后台处理这个请求的线程调用一个I/O完成例程并返回处理下一个请求。并行处理的请求数为n,其中n为InnoDB后台线程数。InnoDB后台线程数由innodb_read_io_threads和innodb_write_io_threads控制。

使用本机AIO,查询线程直接将I/O请求分发给操作系统,从而消除了后台线程数量的限制。InnoDB后台线程等待I/O事件来通知完成的请求。当一个请求完成时,后台线程调用一个I/O完成例程,然后继续等待I/O事件。

本机AIO的优势是可伸缩性,对于I/O绑定严重的系统,通常在SHOW ENGINE INNODB STATUS\G输出中显示许多挂起的读/写。使用本机AIO时并行处理的增加意味着I/O调度器的类型或磁盘阵列控制器的属性对I/O性能有更大的影响。

本机AIO对于大量I/O绑定的系统的一个潜在缺点是无法控制一次分配给操作系统的I/O写请求的数量。分派给操作系统进行并行处理的I/O写请求太多,在某些情况下可能导致I/O读不足,这取决于I/O活动的数量和系统能力。

如果操作系统中异步I/O子系统的问题导致InnoDB无法启动,你可以使用innodb_use_native_aio=0来启动服务器。如果InnoDB检测到一个潜在的问题,比如tmpdir位置,tmpfs文件系统,以及Linux内核不支持tmpfs上的异步I/O,这个选项也可以在启动时自动禁用

MySQL 配置InnoDB的并发线程

配置InnoDB的并发线程
InnoDB使用操作系统线程来处理来自用户事务的请求。(事务可能会在提交或回滚之前向InnoDB发出很多请求。)在具有多核处理器的现代操作系统和服务器上,上下文切换非常高效,大多数工作负载不受并发线程数量的限制而运行良好。MySQL 5.5及以上版本的可伸缩性改进减少了InnoDB需要并发执行线程的数量。

在线程之间最小化上下文切换的情况下,InnoDB可以使用许多技术来限制并发执行的操作系统线程的数量(从而限制同一时间处理的请求的数量)。当InnoDB收到一个来自用户会话的新请求时,如果并发执行的线程数在预定义的限制下,新请求会休眠一段时间,然后重试。一个在休眠后不能重新调度的请求被放入优先/优先出队列并最终被处理。等待锁的线程不计入并发执行的线程数。

可以通过设置配置参数innodb_thread_concurrency来限制并发线程的数量。一旦执行线程的数量达到这个限制,在被放入队列之前,额外的线程将休眠数微秒,由配置参数Innodb_thread_sleep_delay设置。

以前,需要通过实验来找到innodb_thread_sleep_delay的最佳值,而最佳值可能会根据工作负载的不同而变化。在MySQL 5.6.3及以上版本中,你可以设置innodb_adaptive_max_sleep_delay配置选项为innodb_thread_sleep_delay设置最大值,InnoDB会根据当前的线程调度活动自动调整innodb_thread_sleep_delay的大小。这种动态调整有助于线程调度机制在系统负载较轻和正常运行时顺利工作。

innodb_thread_concurrency的默认值和默认的并发线程数限制在不同版本的MySQL和InnoDB中都有改变。innodb_thread_concurrency的默认值是0,因此默认情况下没有并发执行线程的数量限制。

InnoDB只在并发线程数量有限的情况下才会导致线程休眠。当对线程的数量没有限制时,所有线程都平等地进行调度。也就是说,如果innodb_thread_concurrency为0,则忽略innodb_thread_sleep_delay的值。

当线程数量有限制时(当innodb_thread_concurrency为> 0时),InnoDB通过在执行单个SQL语句时允许同时执行多个请求来减少上下文切换的开销,而不用遵守innodb_thread_concurrency设置的限制。由于一条SQL语句(比如join)可能包含在InnoDB内的多个行操作,InnoDB会分配指定数量的“票据”,允许以最小的开销重复调度一个线程。

当一个新的SQL语句启动时,线程没有票据,它必须观察innodb_thread_concurrency。一旦线程被授予进入InnoDB的权限,它就会被分配大量的票据,这些票据可以用来随后进入InnoDB执行行操作。如果票据用完,线程将被驱逐,并且再次观察到innodb_thread_concurrency,这可能会将该线程放入等待线程的先入先出队列中。当线程再次被授予进入InnoDB的权限时,会再次分配票据。分配的票据数量由全局选项innodb_concurrency_tickets指定,默认值为5000。当锁可用时,等待锁的线程将获得一张票据。

这些变量的正确值取决于您的环境和工作负载。尝试一系列不同的值,以确定哪些值适合您的应用程序。在限制并发执行线程的数量之前,检查一下可以提高多核和多处理器计算机上InnoDB性能的配置选项,比如innodb_adaptive_hash_index。

MySQL 配置InnoDB变更缓冲

配置InnoDB变更缓冲
当在表上执行INSERT、UPDATE和DELETE操作时,索引列的值(特别是辅助键的值)通常是无序的,这需要大量的I/O来更新辅助索引。InnoDB有一个更改缓冲区,当相关的辅助索引页面不在缓冲池中时,它将缓存辅助索引的改变,这样就不会立即从磁盘读取页面,从而避免了昂贵的I/O操作。当页面加载到缓冲池时,缓冲的更改将被合并,更新后的页面稍后将刷新到磁盘。InnoDB主线程在服务器几乎空闲的时候,或者在缓慢关闭的时候,合并缓冲的变更。

因为它可以减少磁盘读写,所以更改缓冲区特性对于I/O限制的工作负载最有价值,例如具有大量DML操作(如批量插入)的应用程序。

但是,更改缓冲区占用了缓冲池的一部分,减少了可用来缓存数据页的内存。如果工作集几乎可以放进缓冲池,或者如果表的辅助索引相对较少,那么禁用更改缓冲可能会很有用。如果工作集完全适合缓冲区,那么更改缓冲区不会带来额外的开销,因为它只应用于不在缓冲池中的页。

你可以使用innodb_change_buffering配置参数来控制InnoDB执行改变缓冲的程度。您可以为插入、删除操作(当索引记录最初被标记为删除时)和清除操作(当索引记录被物理删除时)启用或禁用缓冲。更新操作是插入操作和删除操作的组合。innodb_change_buffer的默认值为all。

允许的innodb_change_buffer值包括如下所示:
.all
默认值:缓冲区插入、删除标记操作和清除操作

.none
不缓冲任何操作

.inserts
缓冲插入操作。

.deletes
缓冲delete-marking操作

.changes
缓冲插入和删除标记操作

.purges
缓冲发生在后台的物理删除操作

你可以在MySQL选项文件(my.cnf或my.ini)中设置innodb_change_buffer参数,或者使用set GLOBAL命令动态修改,这需要超级权限。更改设置会影响新操作的缓冲;现有缓冲项的合并不会受到影响。

配置更改缓冲区的最大大小
从MySQL5.6.2开始,innodb_change_buffer_max_size配置选项允许你配置变更缓冲区的最大大小占缓冲池总大小的百分比。默认情况下,innodb_change_buffer_max_size设置为25。最大值为50。

你可以考虑在MySQL服务器上增加innodb_change_buffer_max_size,增加大量的插入、更新和删除活动,其中更改缓冲区的合并跟不上新的更改缓冲区条目,导致更改缓冲区达到其最大大小限制。

用典型的工作负载测试不同的设置,以确定最佳配置。innodb_change_buffer_max_size设置是动态的,允许您在不重启服务器的情况下修改该设置

MySQL 配置InnoDB的内存分配器

配置InnoDB的内存分配器
在开发InnoDB时,操作系统和运行时库提供的内存分配器通常缺乏性能和可伸缩性。那时,还没有针对多核cpu调优的内存分配器库。因此,InnoDB在mem子系统中实现了自己的内存分配器。这个分配器由一个互斥锁保护,这可能成为瓶颈。InnoDB还围绕系统分配器(malloc和free)实现了一个包装器接口,它同样由一个互斥锁保护。

今天,随着多核系统的广泛应用,以及操作系统的成熟,操作系统所提供的内存分配器已经有了显著的改进。与过去相比,这些新的内存分配器性能更好,可伸缩性更强。大多数工作负载,特别是那些经常分配和释放内存的工作负载(比如多表连接),比使用一个内部的、特定于innodb的内存分配器更好的内存分配器。

你可以通过在MySQL选项文件(my.cnf或my.ini)中设置系统配置参数innodb_use_sys_malloc的值来控制InnoDB是使用自己的内存分配器还是操作系统的分配器。如果设置为ON或1(默认值),InnoDB使用底层系统的malloc和free函数,而不是自己管理内存池。该参数为非动态配置,仅在系统启动时生效。如果需要继续使用InnoDB内存分配器,请将innodb_use_sys_malloc设置为0。

当InnoDB内存分配器被禁用时,InnoDB会忽略参数innodb_additional_mem_pool_size的值。InnoDB内存分配器使用一个额外的内存池来满足分配请求,而不必回到系统内存分配器。当InnoDB内存分配器被禁用时,所有这样的分配请求都由系统内存分配器来完成。

在使用动态链接的类似于unixr的系统上,只需让环境变量LD_PRELOAD或LD_LIBRARY_PATH指向实现该分配器的动态库,就可以轻松地替换内存分配器。在其他系统上,可能需要进行一些重新链接。请参考您所选择的内存分配器库的文档。

因为当系统内存分配器被使用时(innodb_use_sys_malloc是ON), InnoDB不能跟踪所有内存的使用情况,所以在SHOW ENGINE InnoDB STATUS命令的输出中BUFFER POOL AND memory部分只包括Total memory allocation中的BUFFER POOL统计信息。任何使用mem子系统或使用ut_malloc分配的内存都被排除在外。