@@ -571,7 +571,7 @@ SELECT * FROM t WHERE id = 1;
571571
572572# ### 优化器
573573
574- # #### 扫描行数
574+ # #### 成本分析
575575
576576优化器是在表里面有多个索引的时候,决定使用哪个索引;或者在一个语句有多表关联(join )的时候,决定各个表的连接顺序。
577577
@@ -581,16 +581,34 @@ SELECT * FROM t WHERE id = 1;
581581
582582在数据库里面,扫描行数是影响执行代价的因素之一,扫描的行数越少意味着访问磁盘的次数越少,消耗的 CPU 资源越少,优化器还会结合是否使用临时表、是否排序等因素进行综合判断
583583
584+
585+
586+ ***
587+
588+
589+
590+ # #### 统计数据
591+
592+ MySQL 中保存着两种统计数据:
593+
594+ * innodb_table_stats 存储了表的统计数据,每一条记录对应着一个表的统计数据
595+ * innodb_index_stats 存储了索引的统计数据,每一条记录对应着一个索引的一个统计项的数据
596+
584597MySQL 在真正执行语句之前,并不能精确地知道满足条件的记录有多少条,只能根据统计信息来估算记录,统计信息就是索引的区分度,一个索引上不同的值的个数(比如性别只能是男女,就是 2 ),称之为基数(cardinality),基数越大说明区分度越好
585598
586- * 通过** 采样统计** 来获取基数,InnoDB 默认会选择 N 个数据页,统计这些页面上的不同值得到一个平均值,然后乘以这个索引的页面数,就得到了这个索引的基数
587- * 数据表是会持续更新的,索引统计信息也不会固定不变,当变更的数据行数超过 1 / M 的时候,会自动触发重新做一次索引统计
599+ 通过** 采样统计** 来获取基数,InnoDB 默认会选择 N 个数据页,统计这些页面上的不同值得到一个平均值,然后乘以这个索引的页面数,就得到了这个索引的基数
600+
601+ 在 MySQL 中,有两种存储统计数据的方式,可以通过设置参数 ` innodb_stats_persistent` 的值来选择:
602+
603+ * ON :表示统计信息会持久化存储(默认),采样页数 N 默认为 20 ,可以通过 ` innodb_stats_persistent_sample_pages ` 指定,页数越多统计的数据越准确,但消耗的资源更大
604+ * 设置为 off 时,表示统计信息只存储在内存,采样页数 N 默认为 8 ,也可以通过系统变量设置(不推荐,每次重新计算浪费资源)
605+
606+ 数据表是会持续更新的,两种更新方式:
588607
589- * 在 MySQL 中,有两种存储索引统计的方式,可以通过设置参数 innodb_stats_persistent 的值来选择:
590- * 设置为 on 时,表示统计信息会持久化存储,这时默认的 N 是 20 ,M 是 10
591- * 设置为 off 时,表示统计信息只存储在内存,这时默认的 N 是 8 ,M 是 16
608+ * 设置 ` innodb_stats_auto_recalc` 为 1 ,当发生变动的记录数量超过表大小的 10 % 时,自动触发重新计算,不过是** 异步进行**
609+ * 调用 ` ANALYZE TABLE t` 手动更新统计信息,只对信息做重新统计(不是重建表),没有修改数据,这个过程中加了 MDL 读锁并且是同步进行,所以会暂时阻塞系统
592610
593- EXPLAIN 执行计划在优化器阶段生成,如果发现 explain 的结果预估的 rows 值跟实际情况差距比较大,可以执行 ` analyze table t ` 重新修正信息,只是对表的索引信息做重新统计(不是重建表),没有修改数据,这个过程中加了 MDL 读锁
611+ EXPLAIN 执行计划在优化器阶段生成,如果 explain 的结果预估的 rows 值跟实际情况差距比较大,可以执行 analyze 命令重新修正信息
594612
595613
596614
@@ -600,7 +618,7 @@ EXPLAIN 执行计划在优化器阶段生成,如果发现 explain 的结果预
600618
601619# #### 错选索引
602620
603- 扫描行数本身是估算数据 ,或者 SQL 语句中的字段选择有问题时,可能导致 MySQL 没有选择正确的执行索引
621+ 采样统计本身是估算数据 ,或者 SQL 语句中的字段选择有问题时,可能导致 MySQL 没有选择正确的执行索引
604622
605623解决方法:
606624
0 commit comments