Fork me on GitHub

5.1 索引单表优化案例

1、案例

create TABLE if not EXISTS `article`(
	`id` int(10) UNSIGNED not null primary key auto_increment,
	`author_id` int(10) UNSIGNED not null,
	`category_id` int(10) UNSIGNED not null,
	`views` int(10) UNSIGNED not null,
	`comments` int(10) UNSIGNED not null,
	`title` VARCHAR(255) not null,
	`content` TEXT not null
);

INSERT into `article`(`author_id`,`category_id`,`views`,`comments`,`title`,`content`) VALUES
(1,1,1,1,'1','1'),
(2,2,2,2,'2','2'),
(1,1,3,3,'3','3');

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

2、分析sql

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

结论 :

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

3、开始优化

# 1.1 新建索引 + 删除索引
#ALTER TABLE `article` ADD INDEX idx_article_ccv(`category_id`,`comments`,`views`);
create index idx_article_ccv on article(category_id,comments,views);

#explain 分析sql

结论 :

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

4、再次优化

#删除索引
drop index idx_article_ccv on article;
#重建索引
create index idx_article_cv on article(category_id,views);
#分析sql
explain SELECT id,author_id FROM article WHERE category_id = 1 AND comments > 1 ORDER BY views DESC LIMIT 1;

结论:

#可以看出,type 变为了ref,Extra 中的Using filesort 也消失了,结果非常理想。

 

关注我的公众号,精彩内容不能错过

posted @ 2017-08-29 17:47  程序员果果  阅读(267)  评论(0编辑  收藏  举报