[MySQL高级](三) 索引分析

悠悠 2022-05-04 00:58 315阅读 0赞

1. 单表

1.1 建表SQL

CREATE TABLE `article` (
`id` int(10) NOT NULL,
`author_id` int(10) DEFAULT NULL,
`category_id` int(10) DEFAULT NULL,
`views` int(10) DEFAULT NULL,
`comments` int(10) DEFAULT NULL,
`title` varchar(255) DEFAULT NULL,
`content` text,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `test`.`article` (`id`, `author_id`, `category_id`, `views`, `comments`, `title`, `content`) VALUES (‘1’, ‘1’, ‘1’, ‘1’, ‘1’, ‘1’, ‘1’);
INSERT INTO `test`.`article` (`id`, `author_id`, `category_id`, `views`, `comments`, `title`, `content`) VALUES (‘2’, ‘2’, ‘2’, ‘2’, ‘2’, ‘2’, ‘2’);
INSERT INTO `test`.`article` (`id`, `author_id`, `category_id`, `views`, `comments`, `title`, `content`) VALUES (‘3’, ‘3’, ‘3’, ‘3’, ‘3’, ‘3’, ‘3’);
INSERT INTO `test`.`article` (`id`, `author_id`, `category_id`, `views`, `comments`, `title`, `content`) VALUES (‘4’, ‘4’, ‘4’, ‘4’, ‘4’, ‘4’, ‘4’);

1.2 案例分析

查询category_id为1且comments大于1的情况下,views最多的article_id

EXPLAIN SELECT
id,
author_id
FROM
article
WHERE
category_id = 1
AND comments > 1
ORDER BY
views DESC
LIMIT 1;

70

➤ 结论:很显然,type是ALL,即最坏的情况。Extra里还出现了Using filesort,也是最坏的情况。优化是必须的。

1.3 开始优化

1.3.1 创建索引 idx_article_ccv

首先,我们根据where后面要查询的字段建立复合索引,即category_id、comments、views。

CREATE INDEX idx_article_ccv ON article (category_id, comments, views);

那么我们再来执行一下,看看测试结果:

70 1

✈ 分析:根据测试结果,key的值为index_article_ccv,说明该索引已经被使用,而且type变成了range,这是可以忍受的,但是Extra中的Using filesort仍然在,这是无法接受的。但是,我们已经建立了索引,为啥没用呢?这是因为按照BTree索引的工作原理,先排序category_id,如果遇到相同的category_id则再排序comments,如果遇到相同的comments则再排序views。当comments字段在联合索引里处于中间位置时,因comments>1条件是一个范围值(所谓range),MySQL无法利用索引再对后面的views部分进行检索,即range类型查询字段后面的索引无效。

那么我们看下面这条SQL的执行情况。

EXPLAIN SELECT
id,
author_id
FROM
article
WHERE
category_id = 1
AND comments = 1 — 注意这里改为了常量
ORDER BY
views DESC
LIMIT 1;

70 2

我们发现,当comments字段的查询条件改为常量1的时候,没有了Using filesort。这说明使用 > 这种范围查询会使后面的索引失效。

1.3.2 创建索引 idx_article_cv

删除刚刚建立的索引

DROP INDEX idx_article_ccv ON article

建立category_id、views索引 idx_article_cv

CREATE INDEX idx_article_cv ON article (category_id, views);

我们再次执行查看执行结果:

70 3

✈ 分析:可以看到,type变为了ref,Extra中的Using filesort也消失了,结果非常理想。

2. 单表

2.1 建表SQL

CREATE TABLE `book` (
`id` int(11) NOT NULL,
`card` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `class` (
`id` int(11) NOT NULL,
`card` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2.2 案例分析

查询两表中card相等的数据

EXPLAIN SELECT
*
FROM
class
LEFT JOIN book ON class.card = book.card

70 4

➤ 结论:type为ALL

2.3 开始优化

2.3.1 创建索引 idx_book_card

这里创建索引有两种方式,我们来看哪种方式更加合适,那么我们先在book表中创建索引idx_book_card

ALTER TABLE book ADD INDEX idx_book_card(card)

那么我们再来执行一下,看看测试结果:

70 5
2.3.2 创建索引 idx_class_card

删除book表的索引,然后创建class表的索引idx_class_card

DROP INDEX idx_book_card ON book;
ALTER TABLE class ADD INDEX idx_class_card(card)

那么我们再来执行一下,看看测试结果:

70 6
✈ 分析:我们之前的博客说过,ref 要好于 index,所以经过实践证明,使用book表的idx_book_card索引更加高效。这是由左连接特性决定的,left join条件用于确定如何从右表搜索行,左边一定都有,所以右表是我们的关键点,一定需要建立索引。需要注意的是,如果条件不允许,只能在左表存在索引,那么我们可以使用右连接,交换两表位置,达到相同的效果。

3. 三表

3.1 建表SQL

在上面的基础上,再创建一个表,SQL语句如下:

CREATE TABLE `phone` (
`id` int(11) NOT NULL,
`card` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

3.2 案例分析

查询三表中card相等的数据

EXPLAIN SELECT
*
FROM
class
LEFT JOIN book ON class.card = book.card
LEFT JOIN phone ON book.card = phone.card

70 7

➤ 结论:type为ALL

2.3 开始优化

2.3.1 创建索引 idx_book_card 和 idx_phone_card

ALTER TABLE phone ADD INDEX idx_phone_card(card)
ALTER TABLE book ADD INDEX idx_book_card(card)

优化后的执行结果为:

70 8

✈ 分析:type都是ref且总rows优化很好,效果不错。因此索引最好设置在需要经常查询的字段中。

总结: JOIN语句的优化

  • 尽可能减少join语句中的NestedLoop的循环总次数:“永远用小结果集驱动大的结果集”。
  • 优先优化NestedLoop的内层循环
  • 保证join语句中被驱动表上Join条件字段已经被索引
  • 当无法保证被驱动表的JOIN条件字段被索引且内存资源充足的前提下,不要太吝啬JoinBuffer的设置。

-——————————

发表评论

表情:
评论列表 (有 0 条评论,315人围观)

还没有评论,来说两句吧...

相关阅读

    相关 MySql高级-索引

    1、索引是什么   索引(Index)是帮助MySQL高效获取数据的数据结构。可以得到索引的本质:索引是数据结构。   可以理解为“排好序的快速查找数据结构”   在数据

    相关 MySQL 高级-索引

    文章归属:http://feiyan.info/16.html  关于MySQL索引的好处,如果正确合理设计并且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和

    相关 MYSQL高级索引

    1.什么是索引? 索引是帮助获取数据的数据结构,排好序的快速查找就是索引。 2.建立索引的数据结构 在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些