文档首页
MySQL 8.4 参考手册
8.4 中文镜像

MySQL 8.4 参考手册 · 中文镜像

正文为中文,英文原文默认隐藏。点击任意中文段落即可展开 / 收起对应英文原文。

打开官方英文原文 ↗

译文由机器翻译生成,仅供理解参考;有疑问请以官方英文原文为准。

MySQL 8.4 参考手册 / 10 优化 / 10.3 优化和索引 / 10.3.8 InnoDB 和 MyISAM 索引统计收集
中文点击中文段落可显示 / 隐藏英文原文本页译文覆盖 100%

10.3.8 InnoDB 和 MyISAM 索引统计信息收集10.3.8 InnoDB and MyISAM Index Statistics Collection

存储引擎收集有关表的统计信息以供优化器使用。表统计信息基于值组,值组是一组具有相同键前缀值的行。对于优化器而言,一个重要的统计信息是平均值组大小。Storage engines collect statistics about tables for use by the optimizer. Table statistics are based on value groups, where a value group is a set of rows with the same key prefix value. For optimizer purposes, an important statistic is the average value group size.

MySQL 在以下方面使用平均值组大小:MySQL uses the average value group size in the following ways:

  • 估算每次 ref 访问必须读取多少行To estimate how many rows must be read for each ref access

  • 要估算部分连接产生的行数,也就是以下形式的操作所产生的行数To estimate how many rows a partial join produces, that is, the number of rows produced by an operation of the form

    (...) JOIN tbl_name ON tbl_name.key = expr
    

随着索引的平均值组大小增加,该索引在这两种用途上的作用就会减弱,因为每次查找的平均行数增加:为了使索引在优化方面有效,最好每个索引值针对表中的较少行。当某个索引值产生大量行时,该索引的作用就会减弱,MySQL 使用它的可能性也会降低。As the average value group size for an index increases, the index is less useful for those two purposes because the average number of rows per lookup increases: For the index to be good for optimization purposes, it is best that each index value target a small number of rows in the table. When a given index value yields a large number of rows, the index is less useful and MySQL is less likely to use it.

平均值组的大小与表的基数有关,即值组的数量。SHOW INDEX 语句显示一个基数值,该值基于 N/S,其中 N 是表中的行数,S 是平均值组大小。该比率给出表中值组的大致数量。The average value group size is related to table cardinality, which is the number of value groups. The SHOW INDEX statement displays a cardinality value based on N/S, where N is the number of rows in the table and S is the average value group size. That ratio yields an approximate number of value groups in the table.

对于基于 <=> 比较运算符的连接,NULL 并不与其他值有所不同:NULL <=> NULL,就像对于任何其他 N 一样,N <=> N。For a join based on the <=> comparison operator, NULL is not treated differently from any other value: NULL <=> NULL, just as N <=> N for any other N.

然而,对于基于 = 运算符的连接,NULL 与非 NULL 值不同:当 expr1 或 expr2(或两者)为 NULL 时,expr1 = expr2 不是 TRUE。这会影响 ref 对形式为 tbl_name.key = expr 的比较的访问:如果 expr 当前值为 NULL,MySQL 不会访问表,因为比较不可能为 TRUE。However, for a join based on the = operator, NULL is different from non-NULL values: expr1 = expr2 is not true when expr1 or expr2 (or both) are NULL. This affects ref accesses for comparisons of the form tbl_name.key = expr: MySQL does not access the table if the current value of expr is NULL, because the comparison cannot be true.

对于 = 比较,表中有多少 NULL 值并不重要。对于优化目的,相关的值是非 NULL 值组的平均大小。然而,目前 MySQL 并未启用收集或使用该平均大小。For = comparisons, it does not matter how many NULL values are in the table. For optimization purposes, the relevant value is the average size of the non-NULL value groups. However, MySQL does not currently enable that average size to be collected or used.

对于 InnoDB 和 MyISAM 表,你可以通过 innodb_stats_method 和 myisam_stats_method 系统变量来对表统计信息的收集进行一定控制。这些变量有三种可能的取值,如下所示:For InnoDB and MyISAM tables, you have some control over collection of table statistics by means of the innodb_stats_method and myisam_stats_method system variables, respectively. These variables have three possible values, which differ as follows:

  • 当变量设置为 nulls_equal 时,所有 NULL 值都被视为相同(也就是说,它们都形成一个单一的值组)。When the variable is set to nulls_equal, all NULL values are treated as identical (that is, they all form a single value group).

    如果 NULL 值组的大小远高于平均非 NULL 值组的大小,这种方法会使平均值组大小向上偏移。这会使优化器认为索引不如它在查找非 NULL 值的连接中实际有用。因此,当优化器本应该使用索引进行 ref 访问时,nulls_equal 方法可能会导致优化器不使用该索引。If the NULL value group size is much higher than the average non-NULL value group size, this method skews the average value group size upward. This makes index appear to the optimizer to be less useful than it really is for joins that look for non-NULL values. Consequently, the nulls_equal method may cause the optimizer not to use the index for ref accesses when it should.

  • 当变量设置为 nulls_unequal 时,NULL 值不被认为是相同的。相反,每个 NULL 值都会形成一个大小为 1 的独立值组。When the variable is set to nulls_unequal, NULL values are not considered the same. Instead, each NULL value forms a separate value group of size 1.

    如果你有很多 NULL 值,这种方法会使平均值组大小向下偏移。如果平均非 NULL 值组大小很大,那么将每个 NULL 值都计为大小为 1 的组会导致优化器高估索引在查找非 NULL 值时的价值。因此,nulls_unequal 方法可能会导致优化器在进行 ref 查找时使用此索引,而其他方法可能更好。If you have many NULL values, this method skews the average value group size downward. If the average non-NULL value group size is large, counting NULL values each as a group of size 1 causes the optimizer to overestimate the value of the index for joins that look for non-NULL values. Consequently, the nulls_unequal method may cause the optimizer to use this index for ref lookups when other methods may be better.

  • 当变量设置为 nulls_ignored 时,NULL 值将被忽略。When the variable is set to nulls_ignored, NULL values are ignored.

如果你倾向于使用许多使用 <=> 而不是 = 的连接,NULL 值在比较中不会特殊处理,一个 NULL 等于另一个。在这种情况下,nulls_equal 是合适的统计方法。If you tend to use many joins that use <=> rather than =, NULL values are not special in comparisons and one NULL is equal to another. In this case, nulls_equal is the appropriate statistics method.

innodb_stats_method 系统变量具有全局值;myisam_stats_method 系统变量既有全局值也有会话值。设置全局值会影响对应存储引擎的表统计信息收集。设置会话值只会影响当前客户端连接的统计信息收集。这意味着您可以通过设置 myisam_stats_method 的会话值,强制使用特定方法重新生成表的统计信息,而不会影响其他客户端。The innodb_stats_method system variable has a global value; the myisam_stats_method system variable has both global and session values. Setting the global value affects statistics collection for tables from the corresponding storage engine. Setting the session value affects statistics collection only for the current client connection. This means that you can force a table's statistics to be regenerated with a given method without affecting other clients by setting the session value of myisam_stats_method.

要重新生成 MyISAM 表的统计信息,您可以使用以下任何方法:To regenerate MyISAM table statistics, you can use any of the following methods:

关于使用 innodb_stats_method 和 myisam_stats_method 的一些注意事项:Some caveats regarding the use of innodb_stats_method and myisam_stats_method:

  • 您可以像上面描述的那样强制显式收集表统计信息。然而,MySQL 也可能自动收集统计信息。例如,在执行某个表的语句过程中,如果其中的一些语句修改了该表,MySQL 可能会收集统计信息。(例如,这可能发生在批量插入或删除,或某些 ALTER TABLE 语句中。)如果发生这种情况,统计信息会使用 innodb_stats_method 或 myisam_stats_method 当时的值进行收集。因此,如果您使用一种方法收集统计信息,但系统变量在稍后自动收集表统计信息时设置为另一种方法,则将使用另一种方法。You can force table statistics to be collected explicitly, as just described. However, MySQL may also collect statistics automatically. For example, if during the course of executing statements for a table, some of those statements modify the table, MySQL may collect statistics. (This may occur for bulk inserts or deletes, or some ALTER TABLE statements, for example.) If this happens, the statistics are collected using whatever value innodb_stats_method or myisam_stats_method has at the time. Thus, if you collect statistics using one method, but the system variable is set to the other method when a table's statistics are collected automatically later, the other method is used.

  • 无法确定用于生成给定表统计信息的方法。There is no way to tell which method was used to generate statistics for a given table.

  • 这些变量仅适用于InnoDB和MyISAM表。其他存储引擎只有一种方法来收集表统计信息。通常它更接近nulls_equal方法。These variables apply only to InnoDB and MyISAM tables. Other storage engines have only one method for collecting table statistics. Usually it is closer to the nulls_equal method.