ANALYZE TABLE 对 InnoDB 表的复杂度取决于
采样页数,由
innodb_stats_persistent_sample_pages定义。表中索引列的数量
分区数量。如果表没有分区,则分区数量被认为是 1。
使用这些参数,估计 ANALYZE TABLE 复杂度的近似公式为
innodb_stats_persistent_sample_pages 的值 * 表中索引列的数量 * 分区数量
通常,结果值越大,ANALYZE TABLE 的执行时间就越长。
innodb_stats_persistent_sample_pages 定义了全局采样页数。要设置单个表的采样页数,请在 CREATE TABLE 或 ALTER TABLE 中使用 STATS_SAMPLE_PAGES 选项。有关更多信息,请参见 第 17.8.10.1 节,“配置持久优化器统计信息参数”。
如果 innodb_stats_persistent=OFF,则采样页数由 innodb_stats_transient_sample_pages 定义。有关其他信息,请参见 第 17.8.10.2 节,“配置非持久优化器统计信息参数”。
为了更深入地了解如何估计 ANALYZE TABLE 复杂度,请考虑以下示例。
在 大 O 表示法 中,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_sample是采样页数(由innodb_stats_persistent_sample_pages定义)n_cols_in_uniq_i是所有唯一索引(不包括主键列)中所有列的总数n_cols_in_non_uniq_i是所有非唯一索引中所有列的总数n_cols_in_pk是主键中列的数量(如果没有定义主键,则InnoDB在内部创建一个单列主键)n_non_uniq_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)
);对于上述算法所需列和索引数据,请查询表 t 的 mysql.innodb_index_stats 持久索引统计信息表。 n_diff_pfx% 统计信息显示了每个索引中计数的列。例如,列 a 和 b 在主键索引中被计数。对于非唯一索引,主键列 (a,b) 以及用户定义的列也被计数。
有关 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 (c和d)n_cols_in_non_uniq_i,所有非唯一索引中所有列的总数,为 4 (e、f、g和h)n_cols_in_pk,主键中列的数量,为 2 (a和b)n_non_uniq_i,表中非唯一索引的数量,为 2 (i2nonuniq和i3nonuniq)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。
并非所有 4 MiB 都需要从磁盘读取,因为某些叶子页可能已经缓存在缓冲池中。