17.8.10.3 InnoDB 表的ANALYZE TABLE 复杂度估算
ANALYZE TABLE
复杂度对 InnoDB 表的依赖项是:
-
由
innodb_stats_persistent_sample_pages
定义的采样页数。 -
表中的索引列数量
-
分区数量。如果一个表没有分区,分区数量被认为是 1。
使用这些参数,可以估算ANALYZE TABLE
复杂度的近似公式为:
innodb_stats_persistent_sample_pages
值 * 表中的索引列数量 * 分区数量
通常,结果值越大,ANALYZE TABLE
的执行时间也越长。
innodb_stats_persistent_sample_pages
定义了全局级别的采样页面数量。要为单个表设置采样页面数量,使用 STATS_SAMPLE_PAGES
选项与CREATE TABLE
或ALTER 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
对表t
。 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 中的数据可能不需要从磁盘中读取,因为一些叶子页面可能已经在缓冲池中被缓存了。