这里我们分成三种情况进行分析,分别是单表,两表,三表

1.单表

CREATE TABLE IF NOT EXISTS `article`(
`id` INT(10) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`author_id` INT(10) NOT NULL,
`category_id` INT(10) NOT NULL,
`views` INT(10) NOT NULL,
`comments` INT(10) NOT NULL,
`title` VARBINARY(255) NOT NULL,
`content` TEXT NOT NULL
);
mysql> select * from article;
+----+-----------+-------------+-------+----------+-------+---------+
| id | author_id | category_id | views | comments | title | content |
+----+-----------+-------------+-------+----------+-------+---------+
| 1 | 1 | 1 | 1 | 1 | 1 | 1 |
| 2 | 2 | 2 | 2 | 2 | 2 | 2 |
| 3 | 1 | 1 | 3 | 3 | 3 | 3 |
+----+-----------+-------------+-------+----------+-------+---------+
3 rows in set (0.00 sec)

案例

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

mysql> EXPLAIN SELECT id,author_id FROM article WHERE category_id=1 AND comments>1 ORDER BY views DESC LIMIT 1;
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------------------+
| 1 | SIMPLE | article | ALL | NULL | NULL | NULL | NULL | 3 | Using where; Using filesort |
+----+-------------+---------+------+---------------+------+---------+------+------+-----------------------------+
1 row in set (0.00 sec)
mysql> show index from article;
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| article | 0 | PRIMARY | 1 | id | A | 3 | NULL | NULL | | BTREE | | |
+---------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
1 row in set (0.00 sec)

#可以看到,type是All,是最坏的情况,extra里还出现了Using filesort,也是最坏的情况,优化是必须的~

#开始优化

#新建索引

CREATE INDEX idx_article_ccv ON `article`(`category_id`,`comments`,`views`)
mysql> show index from article;
+---------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| article | 0 | PRIMARY | 1 | id | A | 3 | NULL | NULL | | BTREE | | |
| article | 1 | idx_article_ccv | 1 | category_id | A | 3 | NULL | NULL | | BTREE | | |
| article | 1 | idx_article_ccv | 2 | comments | A | 3 | NULL | NULL | | BTREE | | |
| article | 1 | idx_article_ccv | 3 | views | A | 3 | NULL | NULL | | BTREE | | |
+---------+------------+-----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
4 rows in set (0.00 sec)
mysql> EXPLAIN SELECT id,author_id FROM article WHERE category_id=1 AND comments>1 ORDER BY views DESC LIMIT 1;
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+---------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+---------------------------------------+
| 1 | SIMPLE | article | range | idx_article_ccv | idx_article_ccv | 8 | NULL | 1 | Using index condition; Using filesort |
+----+-------------+---------+-------+-----------------+-----------------+---------+------+------+---------------------------------------+
1 row in set (0.00 sec)

虽然全表扫描的问题解决了,但是Using filesort问题没有解决~

因为comments>1这个范围导致后面的views索引失效

重新建索引

mysql> show index from article;
+---------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+---------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| article | 0 | PRIMARY | 1 | id | A | 3 | NULL | NULL | | BTREE | | |
| article | 1 | idx_article_cv | 1 | category_id | A | 3 | NULL | NULL | | BTREE | | |
| article | 1 | idx_article_cv | 2 | views | A | 3 | NULL | NULL | | BTREE | | |
+---------+------------+----------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
3 rows in set (0.01 sec)
mysql> EXPLAIN SELECT id,author_id FROM article WHERE category_id=1 AND comments>1 ORDER BY views DESC LIMIT 1;
+----+-------------+---------+------+----------------+----------------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+---------+------+----------------+----------------+---------+-------+------+-------------+
| 1 | SIMPLE | article | ref | idx_article_cv | idx_article_cv | 4 | const | 2 | Using where |
+----+-------------+---------+------+----------------+----------------+---------+-------+------+-------------+
1 row in set (0.00 sec)

这样就比较好接受了

2.两张表

CREATE TABLE IF NOT EXISTS `agency`(
`agency_id` INT(10) NOT NULL AUTO_INCREMENT,
`guide_id` INT(10) NOT NULL,
PRIMARY KEY(`agency_id`)
);
CREATE TABLE IF NOT EXISTS `language`(
`language_id` INT(10) NOT NULL AUTO_INCREMENT,
`guide_id` INT(10) NOT NULL,
PRIMARY KEY(`language_id`)
);
mysql> select * from language;
+-------------+----------+
| language_id | guide_id |
+-------------+----------+
| 1 | 10 |
| 2 | 7 |
| 3 | 3 |
| 4 | 13 |
| 5 | 17 |
| 6 | 4 |
| 7 | 9 |
| 8 | 19 |
| 9 | 16 |
| 10 | 20 |
+-------------+----------+
10 rows in set (0.00 sec) mysql> select * from agency;
+-----------+----------+
| agency_id | guide_id |
+-----------+----------+
| 1 | 2 |
| 2 | 18 |
| 3 | 3 |
| 4 | 20 |
| 5 | 15 |
| 6 | 11 |
| 7 | 13 |
| 8 | 4 |
| 9 | 14 |
| 10 | 10 |
+-----------+----------+
10 rows in set (0.00 sec)

下面开始explain分析

mysql> explain select * from language left join agency on language.guide_id=agency.guide_id;
+----+-------------+----------+------+---------------+------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------------------------------------------+
| 1 | SIMPLE | language | ALL | NULL | NULL | NULL | NULL | 10 | NULL |
| 1 | SIMPLE | agency | ALL | NULL | NULL | NULL | NULL | 10 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------------------------------------------+
2 rows in set (0.00 sec)

type是All,全表扫描

(1)我们首先在TableB也就是agency表加索引(左连接加在右表上)

mysql> alter table `agency` add index `idx_agency`(`guide_id`);

此时再查看一下执行计划

mysql> explain select * from language left join agency on language.guide_id=agency.guide_id;
+----+-------------+----------+------+---------------+------------+---------+--------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------------+---------+--------------------------+------+-------------+
| 1 | SIMPLE | language | ALL | NULL | NULL | NULL | NULL | 10 | NULL |
| 1 | SIMPLE | agency | ref | idx_agency | idx_agency | 4 | db0629.language.guide_id | 1 | Using index |
+----+-------------+----------+------+---------------+------------+---------+--------------------------+------+-------------+
2 rows in set (0.00 sec)

删除索引idx_agency,在左表创建索引

mysql> drop index idx_agency on agency;
mysql> alter table language add index ldx_language(guide_id);
mysql> explain select * from language left join agency on language.guide_id=agency.guide_id;
+----+-------------+----------+-------+---------------+--------------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+-------+---------------+--------------+---------+------+------+----------------------------------------------------+
| 1 | SIMPLE | language | index | NULL | ldx_language | 4 | NULL | 10 | Using index |
| 1 | SIMPLE | agency | ALL | NULL | NULL | NULL | NULL | 10 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+----------+-------+---------------+--------------+---------+------+------+----------------------------------------------------+

这是由左连接特性决定的,left join条件用于确定如何从右表搜索行,左表一定都有,所以右表一定要创建索引~

同理,right join中右表中的数据全都有,所以索引建在左表上

3.三张表的情况

mysql> explain select * from agency left join language on agency.guide_id=language.guide_id left join contact on language.guide_id=contact.guide_id;
+----+-------------+----------+------+---------------+------+---------+------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------------------------------------------+
| 1 | SIMPLE | agency | ALL | NULL | NULL | NULL | NULL | 10 | NULL |
| 1 | SIMPLE | language | ALL | NULL | NULL | NULL | NULL | 10 | Using where; Using join buffer (Block Nested Loop) |
| 1 | SIMPLE | contact | ALL | NULL | NULL | NULL | NULL | 10 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+----------+------+---------------+------+---------+------+------+----------------------------------------------------+
3 rows in set (0.00 sec)

全部全表扫描

加索引

mysql> alter table language add index idx_language(guide_id);
mysql> alter table contact add index idx_contact(guide_id);
mysql> explain select * from agency left join language on agency.guide_id=language.guide_id left join contact on language.guide_id=contact.guide_id;
+----+-------------+----------+------+---------------+--------------+---------+--------------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+----------+------+---------------+--------------+---------+--------------------------+------+-------------+
| 1 | SIMPLE | agency | ALL | NULL | NULL | NULL | NULL | 10 | NULL |
| 1 | SIMPLE | language | ref | idx_language | idx_language | 4 | db0629.agency.guide_id | 1 | Using index |
| 1 | SIMPLE | contact | ref | idx_contact | idx_contact | 4 | db0629.language.guide_id | 1 | Using index |
+----+-------------+----------+------+---------------+--------------+---------+--------------------------+------+-------------+
3 rows in set (0.00 sec)

MySQL索引优化案例的更多相关文章

  1. MySQL索引优化案例浅析

    MySQL是关系型数据库的一种,查询功能强,数据一致性高,数据安全性高,支持二级索引.但是性能比起非关系型数据库稍弱,特别是百万级以上的数据,很容易出现查询慢的现象.这时候要分析慢的原因,一般情况下是 ...

  2. Mysql 索引优化分析

    MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...

  3. 知识点:Mysql 索引优化实战(3)

    知识点:Mysql 索引原理完全手册(1) 知识点:Mysql 索引原理完全手册(2) 知识点:Mysql 索引优化实战(3) 知识点:Mysql 数据库索引优化实战(4) 索引原理知识回顾 索引的性 ...

  4. mySql索引优化分析

    MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...

  5. 深入浅出Mysql索引优化专题分享|面试怪圈

    文章纲要 该文章结合18张手绘图例,21个SQL经典案例.近10000字,将Mysql索引优化经验予以总结,你可以根据纲要来决定是否继续阅读,完成这篇文章大概需要25-30分钟,相信你的坚持是不负时光 ...

  6. mysql索引优化

    mysql 索引优化 >mysql一次查询只能使用一个索引.如果要对多个字段使用索引,建立复合索引. >越小的数据类型通常更好:越小的数据类型通常在磁盘.内存和CPU缓存中都需要更少的空间 ...

  7. MySQL索引优化步骤总结

    在项目使用mysql过程中,随着系统的运行,发现一些慢查询,在这里总结一下mysql索引优化步骤 1.开发过程优化 开发过程中对业务表中查询sql分析sql执行计划(尤其是业务流水表),主要是查看sq ...

  8. MySQL索引优化看这篇文章就够了!

    阅读本文大概需要 5 分钟. 来源:cnblogs.com/songwenjie/p/9410009.html 本文主要讨论MySQL索引的部分知识.将会从MySQL索引基础.索引优化实战和数据库索引 ...

  9. mysql索引优化比普通查询速度快多少

    mysql索引优化比普通查询速度快多少 一.总结 一句话总结:普通查询全表查询,速度较慢,索引优化的话拿空间换时间,一针见血,所以速度要快很多. 索引优化快很多 空间换时间 1.软件层面优化数据库查询 ...

随机推荐

  1. GUC-4 CopyOnWriteArrayList/CopyOnWriteArraySet

    /* * CopyOnWriteArrayList/CopyOnWriteArraySet : “写入并复制” * 注意:添加操作多时,效率低,因为每次添加时都会进行复制,开销非常的大.并发迭代操作多 ...

  2. 编辑器之Sublime Text3、Notepad++

    Sublime text 3 破解版是一款极其强大的代码编辑器,又是一款可以代替记事本的文本编辑器.Sublime text 3拥有着美观的界面和实用的功能,既能够完成代码的编辑又能够完成文本编辑,还 ...

  3. 关闭webstorm自动保存,并显示文件未保存标识

    1.取消自动保存 2.显示编辑状态设置:

  4. 【LOJ】#2131. 「NOI2015」寿司晚宴

    题解 怎么NOI2015D1--全是一眼秒的sb题--然后我代码全都写跪一遍= = 要是NOI2015是IOI赛制我就可以AK啦(大雾) 代码能力直线下降,NOI2018滚粗预定了啊TAT 我是不是要 ...

  5. LoadRunner中InvokeMethod failure: 外部组件发生异常解决办法

    -82801 abnormal termination,caused by mdrv process termination -29996 error:process mmdrv.exe was no ...

  6. ArrayList to Array Conversion in Java

    ArrayList to Array Conversion in Java Following methods can be used for converting ArrayList to Arra ...

  7. 【笔试题】怎样将 GB2312 编码的字符串转换为 ISO-8859-1 编码的字符串?

    笔试题 怎样将 GB2312 编码的字符串转换为 ISO-8859-1 编码的字符串? import java.io.UnsupportedEncodingException; public clas ...

  8. 【Spark亚太研究院系列丛书】Spark实战高手之路-第2章动手实战Scala第3小节:动手实战Scala函数式编程(2)

    3,动手实战Scala中的泛型 泛型泛型类和泛型方法,也就是我们实例化类或者调用方法的时候可以指定其类型,由于Scala的泛型和Java的泛型是一致的,这里不再赘述. 4,动手实战Scala中的隐式转 ...

  9. jquery.autocomplete修改 实现键盘上下键 自动填充

    根据需求要实现通过键盘上下移动,获得联想菜单中的值,如同google baidu的查询功能. 在网上找了很久没有找到可以实现该功能的插件,无奈只能自己动手改代码.找到js中的KEY.DOWN 和 KE ...

  10. ref:ubuntu下如何批量修改文件后缀名

    ref:https://blog.csdn.net/whuslei/article/details/6724900 ubuntu下如何批量修改文件后缀名 正确的方法是: 在命令行中输入   renam ...