4
4
5
5
本章首先讨论了什么是索引统计信息以及 InnoDB 如何处理索引统计信息。然后,您将了解瞬态和持久性统计信息。本章的其余部分介绍如何监视统计信息并更新统计信息。
6
6
7
- ## What Are Index Statistics?
7
+ ## 什么是索引统计?
8
8
9
9
当 MySQL 决定是否使用索引时,归结起来就是 MySQL 认为索引对查询的成效如何。请记住,当您使用辅助索引时,实际上将有一个额外的主键查找来访问数据。辅助索引的排序方式与行的方式不一样,因此使用索引通常意味着随机 I/O(这可以帮助使用覆盖索引)。另一方面,表扫描是更大的顺序 I/O。因此,行对行,执行表扫描比使用辅助索引查找同一行便宜。
10
10
11
11
这意味着,索引要有效,必须筛选出表的很大一部分。必须筛选出多少取决于硬件的性能特征、缓冲池中的表数量、表定义等。在旧旋转磁盘时代,经验法则是,如果需要超过 30% 的行,则首选表扫描。内存中的行数越高,磁盘的随机 I/O 性能越好,此阈值越高。
12
12
13
- ** 注意 覆盖索引会更改此图片,因为它们减少了从跳到实际行数据所需的随机 I/O 量。**
13
+ ------
14
+
15
+ ** 注意** 覆盖索引会更改此图片,因为它们减少了从跳到实际行数据所需的随机 I/O 量。
16
+
17
+ ------
14
18
15
19
这就是索引统计信息的图。优化器(是决定使用哪个查询计划的 MySQL 部分)需要一些简单的方法来确定索引对于给定查询计划的作用。优化器显然知道索引包括哪些列,但此外,它需要一些度量索引筛选行的程度。此信息是索引统计信息提供的信息。因此,索引统计是衡量索引选择性的指标。有两个主要统计信息:唯一值的数量和一定范围内的值数。
16
20
@@ -49,12 +53,20 @@ InnoDB 通过分析索引的随机叶页来计算其索引统计信息。例如
49
53
50
54
将示例页数设置为给定值是什么意思?这取决于索引中的列数。如果只有一列,则该值实际上意味着对叶页数进行采样。但是,对于多列索引,页数是每列。例如,如果将示例页数设置为 20,并且索引中包含四列,则总共采样 4* 20=80 页。
51
55
56
+ ------
57
+
52
58
** 注意 在实践中,索引统计信息采样比本章中描述的要复杂得多。例如,并不总是需要一直下降到叶页。考虑两个相邻的非叶节点何时具有相同的值。然后可以得出结论,最左侧(根据顺序)零件的所有叶页具有相同的值。如果您有兴趣了解更多,一个好的起点是源代码中存储/innobase/dict/dict0stats.cc 文件顶部的注释:https://github.com/mysql/mysql-server/blob/8.0/ 存储/innobase/dict/dict0stats.cc。**
53
59
60
+ ------
61
+
54
62
必须检查多少页才能得到良好的估计?这取决于表。如果数据是统一的,也就是说,每个索引值的行数大致相同,则只需要检查相对较少的页数,并且默认的页数通常就足够了。另一方面,如果您的数据分布非常不规则,则可能需要增加采样页数。非常不规则的数据示例是队列中任务的状态。随着时间的推移,大多数任务将状态为已完成。在最坏的情况下,您可能会体验到所有随机潜水都看到相同的状态,使 InnoDB 得出结论,只有一个值,并且索引作为筛选器毫无价值。
55
63
64
+ ------
65
+
56
66
** 提示 对于只有几行且值用于筛选的数据,下一章中讨论的直方图对于改进查询计划非常有用。**
57
67
68
+ ------
69
+
58
70
表大小也是需要考虑的一个因素。表格越大,一般必须检查的页面越大,才能得到良好的估计。原因是表越大,整个叶页就越有可能指向索引值相同的行。这会降低每个采样页的值,因此为了进行补偿,需要采样更多页面。
59
71
60
72
特殊情况是,InnoDB 已配置为进行比叶页更多的索引潜水。在这种情况下,InnoDB 将检查所有叶页,并在该点停止。这将提供尽可能准确的统计数据。如果在分析期间没有活动事务,则该时间点的统计数据将精确。这包括表中的页数。在本章的稍后部分,您将学习如何在索引和表中查找表的叶页数
@@ -91,8 +103,6 @@ ALTER TABLE world.city
91
103
92
104
93
105
94
-
95
-
96
106
## Persistent Index Statistics
97
107
98
108
MySQL 5.6 中引入了持久索引统计信息,以使查询计划比较旧的瞬态索引统计信息更稳定。如名称建议,启用持久索引统计信息后,将保存统计信息,以便当 MySQL 重新启动时不会丢失统计信息。与单单坚持性更多的差异,尽管将变得清晰。
@@ -119,8 +129,12 @@ MySQL 5.6 中引入了持久索引统计信息,以使查询计划比较旧的
119
129
120
130
请记住,索引统计信息是使用读取未提交的事务隔离级别计算的。虽然在大多数情况下,这是提供最佳统计信息的,但有一个例外。当事务暂时完全更改数据的分布时,可能会导致不正确的统计信息。对表进行完全重建是最极端的情况,也是人们最经常看到的问题。就是在引入这样的innodb_stats_ include_delete_marked选择。InnoDB 仍将将它们包括在统计信息中,而不是将未提交的已删除行视为已删除。该选项仅作为全局选项存在,因此,即使您只有一个表存在此问题,它也会影响所有表。如前所述,另一种选择是禁用受影响表的统计信息自动重新计算,并自己处理。
121
131
132
+ ------
133
+
122
134
** 提示 如果事务对表进行了大的更改(如删除所有行,然后重新生成表),请考虑禁用表的索引统计信息自动重新计算或启用innodb_stats_include_delete_marked。**
123
135
136
+ ------
137
+
124
138
迄今为止,只提到全球选择。如何更改表的索引统计信息设置?由于可以使用 STATS_PERSISTENT 表选项覆盖表的 innodb_stats_persistent 的全局值,因此有一些选项来控制表的持久统计信息的行为方式。表选项是
125
139
126
140
- ** STATS_AUTO_RECALC** :覆盖是否
@@ -129,7 +143,7 @@ MySQL 5.6 中引入了持久索引统计信息,以使查询计划比较旧的
129
143
130
144
可以使用创建表时设置这些选项,也可以在以后使用 ALTER 表设置这些选项,如清单 15-1 所示。
131
145
132
- ```
146
+ ``` sql
133
147
Listing 15 - 1 . Setting the persistent statistics options for a table
134
148
mysql> CREATE SCHEMA IF NOT EXISTS chapter_15;
135
149
Query OK, 1 row affected (0 .4209 sec)
@@ -153,7 +167,6 @@ mysql> ALTER TABLE city
153
167
STATS_SAMPLE_PAGES = 20 ;
154
168
Query OK, 0 rows affected (0 .0280 sec)
155
169
Records: 0 Duplicates: 0 Warnings: 0
156
-
157
170
```
158
171
159
172
首先,创建表城市时禁用自动重新计算并创建 10 个示例页。然后更改设置以启用自动重新计算,并增加示例页数至 20。请注意 ALTER 表如何返回受影响的 0 行。更改持久统计选项只会更改表的元数据,因此它们会立即发生,并且不会影响数据。这意味着您可以根据需要更改设置,而不必担心执行昂贵的操作。例如,您可能希望在批量操作期间禁用自动重新计算。
@@ -259,8 +272,12 @@ sum_of_other_index_sizes: 8
259
272
1 row in set (0.0005 sec)
260
273
```
261
274
275
+ ------
276
+
262
277
** 提示 innodb_index_stats 和innodb_table_stats是常规表。在备份中包含表非常有用,因此如果查询计划突然更改,可以返回并比较统计信息。还可以为具有 UPDATE 权限的用户更新表。这似乎是一个非常有用的属性,但要小心。如果不知道正确的统计信息,您最终会有非常差的查询计划。手动修改索引统计信息几乎不应完成。如果完成,则更改仅在刷新表后生效。**
263
278
279
+ ------
280
+
264
281
如果您觉得innodb_index_ 统计数据和 innodb_table_stats 中有关信息的讨论与 SHOW INDEX 语句以及表和统计信息架构表中可能用于查看的信息类似,那么您就是对的。有一些重叠。由于这些来源也适用于瞬态统计,因此将推迟到讨论瞬态索引统计之后。
265
282
266
283
## Transient Index Statistics
0 commit comments