建筑智库免费网站,企业营销网站模板免费下载,香河建设局网站,wordpress green作者 | adrninistrat0r责编 | 夕颜出品 | CSDN#xff08;ID:CSDNnews#xff09;前言对于非数据库开发人员而言#xff0c;难以对MySQL源码进行分析或调试#xff0c;接近一个黑盒#xff0c;但MySQL提供了一些命令及系统状态变量#xff0c;可对索引及其他内容进行分析… 作者 | adrninistrat0r责编 | 夕颜出品 | CSDNID:CSDNnews前言对于非数据库开发人员而言难以对MySQL源码进行分析或调试接近一个黑盒但MySQL提供了一些命令及系统状态变量可对索引及其他内容进行分析。掌握这些方法后可以尽量深入地了解MySQL的一些实现细节。MySQL索引分析除了EXPLAIN还有什么方法通过以下方法可以获得MySQL索引相关的数据便于分析与理解索引相关的问题。2.1. 通过慢查询日志记录SQL语句执行时间参考 https://dev.mysql.com/doc/refman/5.6/en/slow-query-log.html 。慢查询日志中包含的SQL语句其执行时间超过long_query_time系统参数秒并且至少检查min_examined_row_limit系统参数行。获取初始锁的时间不包含在执行时间中。mysqldMySQL服务器在SQL语句执行且释放所有锁之后将一条语句写入慢查询日志中因此日志顺序可能与执行顺序不同。2.1.1. 慢查询日志的系统参数long_query_time系统参数的最小值为0默认值为10秒。将慢查询日志记录到文件时写入的时间包括微秒部分。将慢查询日志记录到表仅写入整数时间微秒部分将被忽略。默认情况下慢查询日志是禁用的。slow_query_log系统参数可以设置慢查询日志是否启用参数值为0或OFF表示禁用1或ON表示启用。slow_query_log_file系统参数用于设置日志文件名称默认值为“[主机名]-slow.log”。MySQL服务器会在data目录中创建文件除非通过绝对路径名指定了其他目录。log_output系统参数用于设置通用查询日志与慢查询日志的输出位置。其值为一个或多个逗号分隔的单词组成的列表可选值为TABLEFILE及NONE。当指定TABLE时表示将日志记录到名为mysql的系统数据库的general_log与slow_log表中当指定FILE时表示将日志记录到文件中NONE表示禁用日志。不使用索引对行进行查找的查询需要在启用log_queries_not_using_indexes系统变量后才会在写入慢查询日志时被包含进去。该系统默认为关闭。查询缓存处理的查询不会被MySQL服务器记录。2.1.2. 慢查询日志内容格式为了通过慢查询日志记录查询语句的准确耗时需要将慢查询日志保存至文件log_output系统参数需要设置为FILE。慢查询日志文件中每条语句生成的记录都有一行以#开头的数据并包含以下字段所有字段在一行中显示Query_time语句执行时间单位为秒Lock_time获取锁的时间单位为秒Rows_sent发送给客户端的行数Rows_examinedMySQL服务器层检查的行数不包含存储引擎内部的处理。慢查询日志文件中的每个语句之前都有一个SET语句该SET语句包括一个时间戳代表该慢查询语句的记录时间。2.1.3. 开启慢查询日志的参数配置为了开启慢查询日志需要修改MySQL服务器使用的配置文件的“[mysqld]”节点对应的系统参数修改配置文件并重启MySQL服务器程序后生效。通过“set GLOBAL 系统变量xxx”命令修改慢查询日志相关参数时未生效。系统参数设置如下所示slow_query_log 1long_query_time 0min_examined_row_limit 1设置“slow_query_log 1”以开启慢查询日志。设置“long_query_time 0”将每次的查询语句都记录至慢查询日志文件中。设置“min_examined_row_limit 1”可以使explain语句不出现在慢查询日志中因为explain语句的Rows_examined为0。slow_query_log 1long_query_time 0慢查询日志文件默认生成在安装目录的data目录中。使用可视化数据库管理工具连接MySQL时可能会定时发送请求也会生成在慢查询日志文件中。2.1.4. 慢查询日志内容示例慢查询日志内容示例如下# Time: 200311 19:25:39# UserHost: test[test] localhost [127.0.0.1]# Thread_id: 3 Schema: testdb QC_hit: NoQuery_time: 0.015360 Lock_time: 0.001452 Rows_sent: 5222 Rows_examined: 5222use testdb;SET timestamp1583925939;select id,cust_info from test_table_log where cust_info1881;经测试以上Query_time时间仅包含MySQL服务器执行查询操作的耗时不包含客户端展示数据的耗时。2.2. 获取SQL语句读取索引次数通过以下所述的方法可以获取SQL语句执行时读取的索引次数及方法但不会显示读取了哪个索引。2.2.1. SHOW STATUS语句用法参考 https://dev.mysql.com/doc/refman/5.6/en/show-status.html 。SHOW STATUS语句提供服务器状态信息。该语句不需要任何特权只要能连接到服务器即可。SHOW STATUS语句用法如下所示SHOW [GLOBAL | SESSION] STATUS [LIKE pattern | WHERE expr]SHOW STATUS语句接受可选的作用域修饰符可为GLOBAL或SESSION当指定作用域为GLOBAL时SHOW STATUS显示全局的状态值。全局状态变量可以表示服务器本身某些方面的状态或者表示MySQL所有连接的汇总状态。如果某个变量没有全局值则显示会话值当指定作用域为SESSION时SHOW STATUS显示当前连接的状态变量值。如果某个变量没有会话值则显示全局值。LOCAL是SESSION的代名词如果没有指定作用域默认使用SESSION。每次调用SHOW STATUS语句都会使用一个内部临时表并增加全局Created_tmp_tables值。SHOW STATUS语句支持LIKE子句仅显示变量名称与指定模式匹配的行。2.2.2. 与读取索引次数相关的服务器状态变量参考 https://dev.mysql.com/doc/refman/5.6/en/server-status-variables.html 。与读取索引次数相关的服务器状态变量以“HANDLER_READ”开头如下所示Handler_read_first索引中第一个条目的读取索引次数。如果该数值很高则表明服务器正在执行很多全索引扫描例如SELECT col1 FROM foo假设col1列存在索引Handler_read_key基于索引键读取行的请求数即通过索引读取行的数量。如果该数值很高则表明表的索引很合适查询Handler_read_last读取索引中最后一个键的请求数。使用ORDER BY时服务器将发出一个first-key请求对应Handler_read_first然后发出多个next-key对应Handler_read_next请求使用ORDER BY DESC时服务器将发出一个last-key对应Handler_read_last请求然后发出多个previous-key对应Handler_read_prev请求Handler_read_next按索引键顺序读取下一行的请求数。当对索引列使用范围约束进行查询或进行索引扫描时该数值会增加Handler_read_prev按索引键顺序读取上一行的请求数。这种读取方法主要用于优化ORDER BY … DESCHandler_read_rnd基于固定位置读取行的请求数。当执行很多需要对结果进行排序的查询时该数值会很高。可能有很多查询需要MySQL扫描整个表或者联接未正确使用索引键Handler_read_rnd_next读取数据文件下一行的请求数即通过全表扫描读取行的数量。当进行大量全表扫描时该数值会变高。通常这表明表未正确建立索引或者编写的查询未利用索引。2.2.3. 使用SHOW STATUS获取SQL语句读取索引次数当需要获取当前会话的SQL语句读取索引次数可以执行SHOW STATUS查看以“HANDLER_READ”开头的服务器状态变量以下执行命令中的HANDLER_READ大小写不限SHOW STATUS LIKE HANDLER_READ%;若需要使以上数值重置可以重新连接MySQL服务器创建新的会话或重启MySQL服务器程序。2.2.4. SQL语句读取索引次数示例在以下示例中test_table_log表的create_time字段存在单列索引id列为主键。执行以下语句时需要读取索引中第一个记录Handler_read_first值加1。select * from test_table_log order by create_time limit 1;执行以下语句时需要读取索引中的最后一个记录Handler_read_last值加1。select * from test_table_log order by create_time desc limit 1;执行以下语句时需要基于索引读取行Handler_read_key值加1。select * from test_table_log where create_time 2020/3/10 12:23:38 limit 1;
执行以下语句时需要基于索引读取行Handler_read_key值加1并需要根据索引读取后续9行Handler_read_next值增加9。select * from test_table_log where create_time 2020/3/10 12:23:38 limit 10;
执行以下语句时共查询到4条记录需要基于索引读取行Handler_read_key值加1并需要根据索引读取后续行Handler_read_next值增加4。select * from test_table_log where id testtime1583814037num1 and id testtime1583814037num1000执行以下语句时需要读取索引中第一个记录Handler_read_first值加1并需要根据索引读取后续9行Handler_read_next值增加9。select * from test_table_log order by create_time limit 10;执行以下语句时需要读取索引中的最后一个记录Handler_read_last值加1并需要根据索引读取之前的9行Handler_read_prev值增加9。select * from test_table_log order by create_time desc limit 10;执行以下语句时需要通过全表扫描读取数据文件中的行数量为110Handler_read_rnd_next值增加110。select * from test_table_log limit 100,10;执行以下语句时需要通过全表扫描读取数据文件中的行Handler_read_rnd_next值增加超过110并需要对查询到的10条记录进行排序Handler_read_rnd值增加10。select a.* from(select * from test_table_log limit 100,10) as a order by a.create_time;
2.2.5. 查询数据库表获取SQL语句读取索引次数不使用参考 https://dev.mysql.com/doc/refman/5.6/en/status-table.html 。INFORMATION_SCHEMA.GLOBAL_STATUS与INFORMATION_SCHEMA.SESSION_STATUS表与“SHOW GLOBAL STATUS”及“SHOW SESSION STATUS”命令显示对应的信息。查询示例如下select * from INFORMATION_SCHEMA.SESSION_STATUSwhere VARIABLE_NAME like HANDLER_READ% and VARIABLE_VALUE 0order by cast(VARIABLE_VALUE as UNSIGNED INTEGER) desc;
当从上述表查询数据获取SQL语句读取索引次数时会导致Handler_read_rnd_next变量值增大当使用排序时还会导致Handler_read_rnd变量值增大。因此需要获取SQL语句读取索引次数时不通过上述数据库表查询。2.3. 获取InnoDB缓冲池中索引页与记录数InnoDB缓冲池中索引页与记录数可以反映MySQL在执行SQL语句时将指定表的索引读取到缓冲池中的索引页及记录数量。若需要重置InnoDB缓冲池相关数据需要重启MySQL服务器程序未找到其他方法清空InnoDB缓冲池。2.3.1. INNODB_BUFFER_PAGE表参考 https://dev.mysql.com/doc/refman/5.6/en/innodb-information-schema-buffer-pool-tables.html 。InnoDB INFORMATION_SCHEMA缓冲池表提供了缓冲池状态信息以及有关InnoDB缓冲池页面的元数据。InnoDB INFORMATION_SCHEMA缓冲池表中包含INNODB_BUFFER_PAGE该表保存InnoDB缓冲池中每个页的信息。查询INNODB_BUFFER_PAGE或INNODB_BUFFER_PAGE_LRU表可能会影响性能应避免在生产环境查询。2.3.2. INNODB_BUFFER_PAGE表字段参考 https://dev.mysql.com/doc/refman/5.6/en/innodb-buffer-page-table.html 。INNODB_BUFFER_PAGE表中包含以下关注的字段POOL_ID缓冲池ID。是用于区分多个缓冲池实例的标识符。SPACE表空间ID。PAGE_NUMBER页编号page number。PAGE_TYPE页的类型。例如“INDEX”代表B树节点“BLOB”代表未压缩的BLOB页等。TABLE_NAME页所属的表名。该列仅适用于PAGE_TYPE值为INDEX的页。INDEX_NAME页所属的索引名。可以是聚簇索引或二级索引的名称。该列仅适用于PAGE_TYPE值为INDEX的页。NUMBER_RECORDS页的记录的数量。2.3.3. 从INNODB_BUFFER_PAGE表获取InnoDB缓冲池中索引页与记录数从INNODB_BUFFER_PAGE表中可获取InnoDB缓冲池中索引页与记录数table_name字段的形式为“[数据库名].[表名]”。查询的示例语句如下page_num为指定表的指定索引在InnoDB缓冲池中的页的总数record_num为指定表的指定索引在InnoDB缓冲池中记录的总数select TABLE_NAME,INDEX_NAME,count(*) as page_num,sum(NUMBER_RECORDS) as record_numfrom INFORMATION_SCHEMA.INNODB_BUFFER_PAGEwhere table_name testdb.test_table_loggroup by TABLE_NAME,INDEX_NAMEorder by page_num desc;查询结果如下所示
2.4. 获取InnoDB索引页操作次数InnoDB对索引页的操作包括读取、创建及写入等。若需要重置上述数据需要重启MySQL服务器程序。2.4.1. 使用SHOW STATUS获取InnoDB索引页操作次数参考 https://dev.mysql.com/doc/refman/5.6/en/server-status-variables.html 。MySQL服务器状态中包含以下与InnoDB索引页操作次数相关的状态Innodb_buffer_pool_pages_dataInnoDB缓冲池中包含数据的页数。该数量包含脏页与非脏页。Innodb_pages_created对InnoDB表操作创建的页数。Innodb_pages_read对InnoDB表操作从InnoDB缓冲池读取的页数。Innodb_pages_written对InnoDB表操作导致被写的页数。使用SHOW STATUS获取InnoDB索引页操作次数时可执行以下语句SHOW STATUS LIKE Innodb_pages_%;SHOW STATUS LIKE Innodb_buffer_pool_pages_data;2.4.2. 查询数据库表获取InnoDB索引页操作次数参考 https://dev.mysql.com/doc/refman/5.6/en/innodb-buffer-pool-stats-table.html 。INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS表提供了许多与“SHOW ENGINE INNODB STATUS”输出相同的缓冲池信息。上述表包含以下关注的列DATABASE_PAGESInnoDB缓冲池中包含数据的页数。该数量包含脏页与非脏页。与“SHOW STATUS”输出中的Innodb_buffer_pool_pages_data相同。NUMBER_PAGES_READ读取的页数。与“SHOW STATUS”输出中的Innodb_pages_read相同。NUMBER_PAGES_CREATED创建的页数。与“SHOW STATUS”输出中的Innodb_pages_created相同。NUMBER_PAGES_WRITTEN写入的页数。与“SHOW STATUS”输出中的Innodb_pages_written相同。从上述表获取InnoDB索引页操作次数示例语句如下查询操作不会导致以上参数变化select DATABASE_PAGES, NUMBER_PAGES_READ, NUMBER_PAGES_CREATED, NUMBER_PAGES_WRITTEN from INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS;2.4.3. 使用SHOW ENGINE STATUS获取InnoDB索引页操作次数不使用参考 https://dev.mysql.com/doc/refman/5.6/en/show-engine.html 。“SHOW ENGINE”显示指定存储引擎的操作信息。执行时需要“PROCESS”权限。“SHOW ENGINE INNODB STATUS”显示来自标准InnoDB监控器的有关InnoDB存储引擎状态的大量信息。以上输出信息全部包含在Status字段中无法进行过滤不方便单独查看Pages read, created, written等参数。2.5. 获取索引页分裂次数参考 https://dev.mysql.com/doc/refman/5.6/en/index-page-merge-threshold.html 频繁发生页分裂可能对性能产生影响。2.5.1. INFORMATION_SCHEMA.INNODB_METRICS表参考 https://dev.mysql.com/doc/refman/5.6/en/innodb-metrics-table.html 。INFORMATION_SCHEMA.INNODB_METRICS表提供了InnoDB的各种性能信息。每个监控器代表InnoDB源代码中用于收集计数器counter信息的位置。每个计数器可被启动、停止及重置。默认情况下收集的数据比较少。为了启动、停止及重置计算器需要对系统变量innodb_monitor_enable、innodb_monitor_disable、innodb_monitor_reset或innodb_monitor_reset_all进行设置。INFORMATION_SCHEMA.INNODB_METRICS表包含以下关注的列NAME计数器的唯一名称COUNT计数器启用后的计数值STATUSenabled代表计数器在执行disabled代表已停止COMMENT计数器描述。在查询INFORMATION_SCHEMA.INNODB_METRICS表时需要有PROCESS权限。在INFORMATION_SCHEMA.INNODB_METRICS表中存在NAME为“index_page_splits”COMMENT为“Number of index page splits”的记录即索引页分裂次数对应的计数器COUNT列为索引页分裂次数。select count from INFORMATION_SCHEMA.INNODB_METRICS where nameindex_page_splits;2.5.2. 启用索引页分裂次数计数器参考 https://dev.mysql.com/doc/refman/5.6/en/innodb-information-schema-metrics-table.html 。全局变量innodb_monitor_enable、innodb_monitor_disable可分别用于启用、禁用记数器。命令如下所示SET GLOBAL innodb_monitor_enable index_page_splits;
SET GLOBAL innodb_monitor_disable index_page_splits;
innodb_monitor_enable变量还可以MySQL配置文件的[mysqld]节点进行配置可使用半角逗号对多项进行分隔。innodb_monitor_disable不支持在MySQL配置文件配置。经验证对以上系统变量进行设置时需要有SUPER权限root用户。2.6. 获取执行计划参考 https://dev.mysql.com/doc/refman/5.6/en/explain-output.html 。EXPLAIN语句提供有关MySQL如何执行语句的信息。EXPLAIN适用于SELECTDELETEINSERTREPLACE和UPDATE语句。EXPLAIN为SELECT语句中使用的每个表返回一行信息。输出中的表的顺序与MySQL在处理语句时读取表的顺序一致。2.6.1. EXPLAIN输出列EXPLAIN输出的列及含义如下所示2.6.2. idid列为SELECT的标识符其值为查询中SELECT的顺序号。即id列反映了SELECT在执行时的顺序从小到大。2.6.3. select_typeselect_type列为SELECT的类型select_type值及含义如下所示DEPENDENT通常表示使用了相关子查询correlated subquery。2.6.4. typetype列为连接类型描述了表的连接方式。不同的连接类型如下所示system表只有一行系统表。system是const连接类型的特例。const查询的开头读取的表最多只有一行匹配。因为只有一行优化器的其余部分可以将此行中对应列的值视为常量。const连接类型对应的表查询非常快因为它们只读取一次。将主键或唯一索引的所有部分与常量值进行比较时会使用const连接类型。在以下示例中tbl_name表可以作为const连接类型使用SELECT * FROM tbl_name WHERE primary_key1;
SELECT * FROM tbl_name WHERE primary_key_part11 AND primary_key_part22;
eq_ref对于先前的表的每种行组合从eq_ref连接类型对应的表中读取一行。除了system和const连接类型外eq_ref是最好的联接类型。当连接使用索引的所有部分并且索引是主键或非空唯一索引时将使用eq_ref连接类型。eq_ref可用于使用运算符进行比较的索引列。比较值可以是常量也可以是使用在此表之前读取的表中列的表达式。在以下示例中MySQL可以使用eq_ref连接类型处理ref_table表SELECT * FROM ref_table,other_table WHERE ref_table.key_columnother_table.column;
SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1other_table.column AND ref_table.key_column_part21;
ref对于先前的表的每种行组合从ref连接类型对应的表读取所有具有匹配索引值的行。如果连接仅使用索引键的最左前缀或者索引键不是主键或唯一索引即连接不能基于索引键值选择单行则使用ref连接类型。如果使用的键只匹配少量几行则ref是一个好的连接类型。ref连接类型可用于使用或运算符进行比较的索引列。在以下示例中MySQL可以使用ref连接类型处理ref_table表SELECT * FROM ref_table WHERE key_columnexpr;
SELECT * FROM ref_table,other_table WHERE ref_table.key_columnother_table.column;
SELECT * FROM ref_table,other_table WHERE ref_table.key_column_part1other_table.column AND ref_table.key_column_part21;
fulltext使用全文索引执行连接。ref_or_nullref_or_null与ref类似区别在于使用ref_or_null时MySQL对包含NULL值的行进行了额外搜索。ref_or_null连接类型最常用于解决子查询。在以下示例中MySQL可以使用ref_or_null连接类型处理ref_table表SELECT * FROM ref_table WHERE key_columnexpr OR key_column IS NULL;
index_mergeindex_merge连接类型表示使用了索引合并优化。在这种情况下输出行中的key列包含使用的索引列表key_len列包含所用索引的最长键部分列表。unique_subqueryunique_subquery连接类型在某些使用IN的子查询的情况下替代eq_ref如下所示value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery只是一个索引查找函数可以完全替代子查询以提高效率。index_subqueryindex_subquery连接类型与unique_subquery类似它替代了IN子查询支持子查询中的非唯一索引如下所示value IN (SELECT key_column FROM single_table WHERE some_expr)
rangerange连接类型表示仅检索给定范围内的行使用索引选择行。EXPLAIN输出行中的key列表示使用哪个索引。key_len列包含使用的最长的索引键部分。对于此连接类型ref列为NULL。使用 IS NULLBETWEENLIKE或IN()运算符中的任何一个将索引键列与常量进行比较时可以使用range类型。indexindex连接类型与ALL类型类似区别在于index连接类型有对索引树进行扫描。有两种方式a. 如果查询的索引是覆盖索引并且可满足所需表的所有数据则仅扫描索引树。在这种情况下Extra列显示“Using index”。仅扫描索引通常比ALL连接类型快因为索引的大小通常小于表数据。b. 对指定索引读取数据进行全表扫描以按索引顺序查找数据行。Extra列不会显示“Using index”。当查询仅使用属于单个索引一部分的列时MySQL可以使用此连接类型。ALL对之前的表中的每个行组合进行全表扫描。如果当前表是第一个没有标记为const的表这通常是不好的并且通常在所有其他情况下非常糟糕。通常可以通过添加索引来避免ALL连接类型这些索引基于常量值或先前的表的列值启用从该表的行检索。2.6.5. possible_keyspossible_keys列表示MySQL可以选择用于查找此表的行的索引。请注意此列于EXPLAIN输出中显示的表的顺序完全独立。假如possible_keys列为NULL说明没有相关的索引。2.6.6. keykey列表示MySQL实际决定使用的索引键。如果MySQL决定使用其中一个possible_keys索引来查找行那么该索引将被显示在key列中。如果key列为NULL说明MySQL未找到更有效执行查询的索引。要强制MySQL使用或忽略possible_keys列中列出的索引请在查询中使用FORCE INDEXUSE INDEX或IGNORE INDEX。2.6.7. key_lenkey_len列表示MySQL决定使用的索引键的长度。根据key_len的值可以确定MySQL实际使用了联合索引的多少部分。由于索引键的存储格式可以为NULL的列比不允许为NULL的列的索引键长度大1。2.6.8. refref列显示了在key列中列出的用于从表中查询行的索引与哪些列或常量进行了比较。如果ref列的值为func说明使用的值是某些函数的结果。2.6.9. rowsrows列表示MySQL认为执行查询时必须检查的行数。对于InnoDB表该数字是估计值可能并不总是准确的。2.6.10. ExtraExtra列包含MySQL如何解决查询的额外信息。以下为Extra列的部分可能的值及说明Using filesort出现该提示说明MySQL在进行排序时需要使用filesort未使用索引进行排序。Using index从表中检索列信息时仅使用索引树的信息不需要进行额外的查找以读取实际行。当仅查询属于单个索引的部分列时可以使用此策略。对于具有用户定义的聚簇索引的InnoDB表即使Extra列中没有出现“Using index”对应的索引也可能被使用。当type列为index且key列为主键时对应以上情况。Using index condition出现该提示说明MySQL在查询时使用了索引条件下推。Using sort_union(…), Using union(…), Using intersect(…)以上显示了对应index_merge连接类型即使用索引合并时索引扫描合并时使用的特定算法。Using temporary为了解决该查询MySQL需要创建一个临时表来保存结果。如果查询包含GROUP BY和ORDER BY子句且列出了不同的列时通常会发生这种情况。Using whereWHERE子句用于限制与下一个表匹配的行或发送到客户端的行。假如Extra列的值不是using where且表的连接类型为ALL或index时则说明查询语句存在一些问题除非是特意为了获取或检查表中所有的行。3. InnoDB读取索引页时机InnoDB读取索引页的时机包括但不限于MySQL启动、执行EXPLAIN语句、执行查询/插入/更新操作等情况。为了获取InnoDB读取索引页的次数可参考前文查询以“Innodb_pages_”开头的系统状态或从INFORMATION_SCHEMA.INNODB_BUFFER_POOL_STATS表查询。3.1. MySQL启动时读取索引页当MySQL启动时会读取对部分表的索引。此时还未执行任何语句查看InnoDB读取索引页的次数大于0查看InnoDB缓冲池中索引页与记录数大于0。3.2. 执行EXPLAIN语句时读取索引页在执行EXPLAIN语句时可能会读取相关表对应的索引页若所需的索引页数据已被读取至缓冲池中可能不会读取。对于上述情况可查看InnoDB读取索引页的次数执行EXPLAIN语句后次数会增加。3.3. 执行插入/查询/更新/删除语句时读取索引页在执行插入/查询/更新/删除语句时可能会读取相关表对应的索引页若所需的索引页数据已被读取至缓冲池中可能不会读取。4. 参考资料以上参考的资料如下https://dev.mysql.com/doc/refman/5.6/en/推荐阅读什么一个核同时执行两个线程征战云时代为什么安全是关键命题25 张图读懂「文件系统」数据平台、大数据平台、数据中台……傻傻分不清这次终于有人讲明白了Java 二十五载正在 Kotlin 化维度爆炸Python实现数据压缩如此简单