MySQL索引优化策略(二):多个索引应该建立为独立索引还是联合索引?

 2024-01-16 04:03:07  阅读 0

人们常常缺乏对多列索引的理解。 常见的错误是为许多列设置独立索引,或者对索引列使用错误的顺序。 我们将在下一篇文章中讨论索引列顺序的问题。 首先我们看一下多列独立索引的情况。 以下面的表结构为例:

CREATE TABLE test (
  c1 INT,
  c2 INT,
  c3 INT,
  KEY(c1),
  KEY(c2),
  KEY(c3),
);

这种索引策略的使用通常是一些权威建议的结果(例如为 WHERE 条件中使用的条件列添加索引)。 事实上,这是完全错误的。 如果要评价的话,只能给1星。 以这种方式建立的索引比真正优化的索引慢几个数量级。 有时,当您无法设计三颗星以上的索引时,最好专注于优化行顺序或创建覆盖索引,而不是忽略 WHERE 条件。

覆盖索引(index)是指执行一条查询语句时只能从索引中获取,而不从数据表中读取。 也可以称为实现索引覆盖。 当一条查询语句满足覆盖索引条件时,MySQL只需要使用该索引即可返回查询所需的数据。 这样就避免了找到索引然后返回表的操作,减少了I/O,提高了效率。 例如表e中有一个公共索引(key1,key2)。 当我们传递SQL语句:key2 from e where key1 = '';时,我们就可以通过覆盖索引进行查询,而不需要从数据表中查找数据行。

在许多情况下,在许多列上创建独立索引并不能帮助 MySQL 提高性能。 MySQL 5.0及更新版本可以使用索引合并策略稍微优化这种类型的设计——这种方法允许对具有多列索引的表进行查询,以限制使用索引来定位所需的数据行。

索引合并就是对多个索引进行条件扫描,然后合并各自的结果(/union)

早期版本的MySQL只能使用一个索引,因此在没有索引辅助的情况下,MySQL通常会进行全表扫描。 例如,表上有一个 and 索引,但在 WHERE 条件中使用两个索引并不是一个好的选择:

SELECT film_id, actor_id FROM film_actor WHERE actor_id = 1 OR film_id = 1;

在早期版本的 MySQL 中,此查询将导致全表扫描,除非您像以下语句一样连接两个查询。

SELECT film_id, actor_id FROM film_actor WHERE actor_id = 1 UNION ALL 
SELECT film_id, actor_id FROM film_actor WHERE film_id = 1 AND actor_id <> 1;

在MySQL 5.0之后的版本中,查询将使用两个索引并合并最终结果。 实现此过程需要算法的三种变体:

使用 OR 条件来获取并集数据。 使用 AND 条件获取交集数据。 将上述两步的数据进行交集,然后求并集。

上面的内容有点混乱。 其实应该是分布使用单个条件(为了使用索引)找到所有数据,然后将数据组合起来。 使用下面的方法检查一下。

EXPLAIN SELECT `film_id`,`actor_id` FROM `film_actor` WHERE `actor_id`=1 OR `film_id`=1

可以看到查询方式是全表扫描,但是使用了Extra进行优化。 MySQL 在处理负责任的查询时使用这种技术,因此您可能会在 Extra 中看到嵌套操作。 这种索引合并策略有时可以很好地发挥作用,但更多时候它应该被视为索引使用不良的指标:

当服务器使用交集索引(通常使用AND条件)时,通常意味着您需要一个包含所有相关列的索引,而不是组合单独的索引列。 当服务器使用联合索引(通常使用OR条件)时,有时缓存、排序和合并操作会占用大量CPU和内存资源,特别是当索引并不总是可过滤时,这会导致扫描返回大量数字用于合并操作的数据行。 请记住,优化器不承担这些成本 - 它只是优化随机页面读取的数量。 这将使查询“无价”,导致全表扫描实际上更慢。 高 CPU 和内存使用率会影响并发查询,但单独运行查询语句时不会出现这些影响。 因此,有时最好像 MySQL 4.1 中那样重写使用 UNION 的查询。

当您在使用分析时看到索引合并时,您应该检查查询和表结构,看看这是否是最佳方法。 您可以通过使用(优化开关)禁用索引合并来检查这一点。

然后将索引改为联合索引(删除原来的两列独立索引和),看看效果。 可以看到此时避免了全表查询。

ALTER TABLE film_actor ADD INDEX `sindex` (`film_id`,`actor_id`);

标签: 索引 查询 合并

如本站内容信息有侵犯到您的权益请联系我们删除,谢谢!!


Copyright © 2020 All Rights Reserved 京ICP5741267-1号 统计代码