Documentation Home
MySQL 8.4 Reference Manual
Related Documentation Download this Manual
PDF (US Ltr) - 39.8Mb
PDF (A4) - 39.9Mb
Man Pages (TGZ) - 257.9Kb
Man Pages (Zip) - 364.9Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


MySQL 8.4 Reference Manual  /  ...  /  Estimating ANALYZE TABLE Complexity for InnoDB Tables

17.8.10.3 InnoDB 表的ANALYZE TABLE 复杂度估算

ANALYZE TABLE 复杂度对 InnoDB 表的依赖项是:

使用这些参数,可以估算ANALYZE TABLE 复杂度的近似公式为:

innodb_stats_persistent_sample_pages 值 * 表中的索引列数量 * 分区数量

通常,结果值越大,ANALYZE TABLE 的执行时间也越长。

Note

innodb_stats_persistent_sample_pages 定义了全局级别的采样页面数量。要为单个表设置采样页面数量,使用 STATS_SAMPLE_PAGES 选项与CREATE TABLEALTER TABLE。更多信息,请见第17.8.10.1节,“配置持久优化器统计参数”

如果innodb_stats_persistent=OFF,采样页面数量由innodb_stats_transient_sample_pages定义。更多信息,请见第17.8.10.2节,“配置非持久优化器统计参数”

为了更深入地了解ANALYZE TABLE复杂度,请考虑以下示例。

Big O notation中,ANALYZE TABLE复杂度被描述为:

 O(n_sample
  * (n_cols_in_uniq_i
     + n_cols_in_non_uniq_i
     + n_cols_in_pk * (1 + n_non_uniq_i))
  * n_part)

其中:

  • n_样本 是采样的页面数量(由innodb_stats_persistent_sample_pages定义)

  • n_cols_in_唯一_i 是所有唯一索引中的总列数(不包括主键列)

  • n_cols_in_non_唯一_i 是所有非唯一索引中的总列数

  • n_cols_in_pk 是主键中的列数(如果未定义主键,InnoDB 将创建一个单独的内部主键)

  • n_non_唯一_i 是表中的非唯一索引数量

  • n_part 是分区的数量。 如果没有定义分区,表将被视为单个分区。

现在,考虑以下表(表t),它具有主键(2列)、唯一索引(2列)和两个非唯一索引(每个2列):

CREATE TABLE t (
  a INT,
  b INT,
  c INT,
  d INT,
  e INT,
  f INT,
  g INT,
  h INT,
  PRIMARY KEY (a, b),
  UNIQUE KEY i1uniq (c, d),
  KEY i2nonuniq (e, f),
  KEY i3nonuniq (g, h)
);

为了根据上述算法所需的列和索引数据,查询persistent index statistics表mysql.innodb_index_stats对表tn_diff_pfx%统计信息显示每个索引中被计数的列。例如,对于主键索引,列ab被计数。对于非唯一索引,主键列(a,b)在用户定义的列之外还被计数。

Note

关于 InnoDB 持久统计表的更多信息,请见第17.8.10.1节,“配置持久优化器统计参数”

mysql> SELECT index_name, stat_name, stat_description
       FROM mysql.innodb_index_stats WHERE
       database_name='test' AND
       table_name='t' AND
       stat_name like 'n_diff_pfx%';
  +------------+--------------+------------------+
  | index_name | stat_name    | stat_description |
  +------------+--------------+------------------+
  | PRIMARY    | n_diff_pfx01 | a                |
  | PRIMARY    | n_diff_pfx02 | a,b              |
  | i1uniq     | n_diff_pfx01 | c                |
  | i1uniq     | n_diff_pfx02 | c,d              |
  | i2nonuniq  | n_diff_pfx01 | e                |
  | i2nonuniq  | n_diff_pfx02 | e,f              |
  | i2nonuniq  | n_diff_pfx03 | e,f,a            |
  | i2nonuniq  | n_diff_pfx04 | e,f,a,b          |
  | i3nonuniq  | n_diff_pfx01 | g                |
  | i3nonuniq  | n_diff_pfx02 | g,h              |
  | i3nonuniq  | n_diff_pfx03 | g,h,a            |
  | i3nonuniq  | n_diff_pfx04 | g,h,a,b          |
  +------------+--------------+------------------+

根据上述索引统计数据和表定义,可以确定以下值:

  • n_cols_in_uniq_i,所有唯一索引中除主键列外的所有列总数,为2(cd)

  • n_cols_in_non_uniq_i,所有非唯一索引中的所有列总数,为4(efgh)

  • n_cols_in_pk,主键中的列总数,为2(ab)

  • n_non_uniq_i,表中非唯一索引的数量,为2(i2nonuniqi3nonuniq))

  • n_part,分区的数量,为1。

现在可以通过计算 innodb_stats_persistent_sample_pages * (2 + 4 + 2 * (1 + 2)) * 1 来确定被扫描的叶子页面数量。将 innodb_stats_persistent_sample_pages 设置为默认值 20,并且使用默认页面大小16 KiB (innodb_page_size=16384),可以估算表 t 的20 * 12 * 16384 字节将被读取,约为4 MiB。

Note

所有 4 MiB 中的数据可能不需要从磁盘中读取,因为一些叶子页面可能已经在缓冲池中被缓存了。