mysql 翻译系列 三十

2025-03-07  本文已影响0人  如风_dcac

10.3.8 InnoDB和MyISAM索引统计信息收集

存储引擎会收集表的统计信息,以供优化器使用。表统计信息基于值组,值组是指具有相同键前缀值的一组行。对于优化器而言,一个重要的统计信息是平均 值组大小。

MySQL以以下方式使用平均 值组大小:

随着索引的平均 值组大小增加,该索引对于上述两个目的的作用就会降低,因为每次查找的平均行数增加了。为了让索引对优化更有帮助,最好是每个索引值能定位到表中的少量行。当一个给定的索引值产生大量行时,该索引的作用就会降低,MySQL使用它的可能性也会降低。

平均 值组大小与表的基数相关,基数即值组的数量。SHOW INDEX语句会显示一个基于N/S的基数,其中N是表中的行数,S是平均 值组大小。这个比率给出了表中值组的大致数量。

对于基于<=>比较运算符的连接,NULL与其他任何值的处理方式没有区别:NULL <=> NULL,就像对于任何其他NN <=> N一样。

然而,对于基于=运算符的连接,NULL与非NULL值是不同的:当expr1expr2(或两者)为NULL时,expr1 = expr2不成立。这会影响形如tbl_name.key = expr的比较的ref访问:如果expr的当前值为NULL,MySQL不会访问表,因为这个比较不可能为真。

对于=比较,表中有多少个NULL值并不重要。为了优化目的,相关的值是非NULL值组的平均大小。不过,MySQL目前无法收集或使用这个平均大小。

对于InnoDB和MyISAM表,你可以分别通过innodb_stats_methodmyisam_stats_method系统变量对表统计信息的收集进行一定程度的控制。这些变量有三个可能的值,区别如下:

如果你倾向于使用许多基于<=>而不是=的连接,在比较中NULL值并不特殊,一个NULL值等于另一个NULL值。在这种情况下,nulls_equal是合适的统计方法 。

innodb_stats_method系统变量有一个全局值;myisam_stats_method系统变量有全局值和会话值。设置全局值会影响来自相应存储引擎的表的统计信息收集。设置会话值仅会影响当前客户端连接的统计信息收集。这意味着你可以通过设置myisam_stats_method的会话值,强制使用给定的方法重新生成表的统计信息,而不会影响其他客户端。

要重新生成MyISAM表的统计信息,可以使用以下任何一种方法:

关于innodb_stats_methodmyisam_stats_method的使用,有一些注意事项:

10.3.9 B树索引与哈希索引的比较

理解B树和哈希数据结构,有助于预测不同查询在使用这些数据结构构建索引的不同存储引擎上的性能表现,特别是对于允许选择B树索引或哈希索引的MEMORY存储引擎。

B树索引的特点

  1. 适用运算符:B树索引可用于在使用=>>=<<=BETWEEN运算符的表达式中进行列比较。如果LIKE的参数是不以通配符开头的常量字符串,该索引也可用于LIKE比较。例如,以下SELECT语句会使用索引:
SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%'; 
SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%';

在第一条语句中,仅会考虑'Patrick' <= key_col < 'Patricl'的行;在第二条语句中,仅会考虑'Pat' <= key_col < 'Pau'的行。

  1. 不适用情况:以下SELECT语句不会使用索引:
SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%'; 
SELECT * FROM tbl_name WHERE key_col LIKE other_col;

第一条语句中,LIKE的值以通配符开头;第二条语句中,LIKE的值不是常量。

  1. 长字符串匹配优化:如果使用... LIKE '%string%'string长度超过三个字符,MySQL会使用Turbo Boyer-Moore算法初始化字符串的模式,然后利用该模式更快地执行搜索。
  2. IS NULL查询:如果col_name被索引,使用col_name IS NULL的搜索会使用索引。
  3. WHERE子句限制:任何未覆盖WHERE子句中所有AND层级的索引,都不会用于优化查询。也就是说,为了能够使用索引,索引的前缀必须在每个AND组中被使用。
  4. 索引使用情况示例:以下WHERE子句会使用索引:
... WHERE index_part1=1 AND index_part2=2 AND other_column=3;
/* index = 1 OR index = 2 */... WHERE index=1 OR A=10 AND index=2;
/* 优化为 "index_part1='hello'" */... WHERE index_part1='hello' AND index_part3=5;
/* 可使用index1上的索引,但不能使用index2或index3上的索引 */... WHERE index1=1 AND index2=2 OR index1=3 AND index3=3;

这些WHERE子句不会使用索引:

/* index_part1未被使用 */... WHERE index_part2=1 AND index_part3=2;
/* 索引未在WHERE子句的两个部分中使用 */... WHERE index=1 OR A=10;
/* 没有索引覆盖所有行 */... WHERE index_part1=1 OR index_part2=10;
  1. 索引未使用情况:有时,即使存在可用索引,MySQL也不会使用。一种情况是,当优化器估计使用索引需要MySQL访问表中很大比例的行时(在这种情况下,全表扫描可能会快得多,因为查找次数更少)。不过,如果这样的查询使用LIMIT仅检索部分行,MySQL仍会使用索引,因为它可以更快地找到要返回的少量行。

哈希索引的特点

哈希索引与上述B树索引的特点有所不同:

  1. 适用运算符:哈希索引仅用于使用=<=>运算符的相等比较(但速度非常快),不用于诸如<等查找值范围的比较运算符。依赖这种单值查找的系统被称为 “键值存储”;若要在这类应用中使用MySQL,应尽可能使用哈希索引。
  2. ORDER BY操作:优化器无法使用哈希索引加速ORDER BY操作(这种类型的索引不能用于按顺序搜索下一个条目)。
  3. 行数估算:MySQL无法确定两个值之间大约有多少行(范围优化器会利用这一点来决定使用哪个索引)。如果将MyISAM或InnoDB表更改为哈希索引的MEMORY表,这可能会影响某些查询。
  4. 搜索限制:只能使用完整的键来搜索行(而B树索引可以使用键的任何最左前缀来查找行)。
上一篇 下一篇

猜你喜欢

热点阅读