MySQL索引优化案例
这里我们分成三种情况进行分析,分别是单表,两表,三表
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索引优化案例的更多相关文章
- MySQL索引优化案例浅析
MySQL是关系型数据库的一种,查询功能强,数据一致性高,数据安全性高,支持二级索引.但是性能比起非关系型数据库稍弱,特别是百万级以上的数据,很容易出现查询慢的现象.这时候要分析慢的原因,一般情况下是 ...
- Mysql 索引优化分析
MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...
- 知识点:Mysql 索引优化实战(3)
知识点:Mysql 索引原理完全手册(1) 知识点:Mysql 索引原理完全手册(2) 知识点:Mysql 索引优化实战(3) 知识点:Mysql 数据库索引优化实战(4) 索引原理知识回顾 索引的性 ...
- mySql索引优化分析
MySQL索引优化分析 为什么你写的sql查询慢?为什么你建的索引常失效?通过本章内容,你将学会MySQL性能下降的原因,索引的简介,索引创建的原则,explain命令的使用,以及explain输出字 ...
- 深入浅出Mysql索引优化专题分享|面试怪圈
文章纲要 该文章结合18张手绘图例,21个SQL经典案例.近10000字,将Mysql索引优化经验予以总结,你可以根据纲要来决定是否继续阅读,完成这篇文章大概需要25-30分钟,相信你的坚持是不负时光 ...
- mysql索引优化
mysql 索引优化 >mysql一次查询只能使用一个索引.如果要对多个字段使用索引,建立复合索引. >越小的数据类型通常更好:越小的数据类型通常在磁盘.内存和CPU缓存中都需要更少的空间 ...
- MySQL索引优化步骤总结
在项目使用mysql过程中,随着系统的运行,发现一些慢查询,在这里总结一下mysql索引优化步骤 1.开发过程优化 开发过程中对业务表中查询sql分析sql执行计划(尤其是业务流水表),主要是查看sq ...
- MySQL索引优化看这篇文章就够了!
阅读本文大概需要 5 分钟. 来源:cnblogs.com/songwenjie/p/9410009.html 本文主要讨论MySQL索引的部分知识.将会从MySQL索引基础.索引优化实战和数据库索引 ...
- mysql索引优化比普通查询速度快多少
mysql索引优化比普通查询速度快多少 一.总结 一句话总结:普通查询全表查询,速度较慢,索引优化的话拿空间换时间,一针见血,所以速度要快很多. 索引优化快很多 空间换时间 1.软件层面优化数据库查询 ...
随机推荐
- Python/Anaconda多版本共存的解决方案
博客中的文章均为 meelo 原创,请务必以链接形式注明 本文地址 虽然Python2大势已去,众多项目都已经支持Python3,但总有一些教程和项目只支持Python2.通常情况是计算机里既装着Py ...
- virtualenv python的虚拟环境
官网:https://virtualenv.pypa.io/en/stable/userguide/ virtualenv通过创建独立Python开发环境的工具, 来解决依赖.版本问题 基本使用: d ...
- 【LOJ】 #2521. 「FJOI2018」领导集团问题
题解 这道题很显然可以想出来一个\(n^2\)的dp,也就是dp[u][i]表示以u为根的子树最大值是i的点集最大是多少(i是离散化后的值) 就是对于每个儿子处理出后缀最大值然后按位相加更新父亲,我们 ...
- POJ 1597 Function Run Fun
记忆化搜索. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> ...
- 「BZOJ4763」雪辉
「BZOJ4763」天野雪辉 题目大意:有一棵 \(n\) 个点的树,树上每一个点有权值 \(a_i \leq 30000\) ,每次询问给出若干路径,求出这些路径的并上面的不同颜色数与 \(mex\ ...
- 【tarjan】BZOJ2140-稳定婚姻
又名NTR的故事 [题目大意] n对夫妻Bi和Gi.若某男Bi与某女Gj曾经交往过,他们有私奔的可能性.不妨设Bi和Gj旧情复燃,进而Bj会联系上了他的初恋情人Gk,以此递推.若在Bi和Gi离婚的前提 ...
- [转]android系统各种音量的获取与设置
获取系统音量 通过程序获取android系统手机的铃声和音量.同样,设置铃声和音量的方法也很简单! 设置音量的方法也很简单,AudioManager提供了方法:publicvoidsetStreamV ...
- Backbone.js 的最佳应用场景有哪些?#zhihu#
这段时间,想再次了解下backbone js的相关知识,就把一些认为不错的拿过来了: 新版的有道笔记 Web 版(http://note.youdao.com)也使用了 Backbone.就像其他答案 ...
- iOS开发经验总结——基础工程
iOS开发经验总结--依赖库 这篇博客,我想说一下开发中经常遇到的一个问题,虚拟个场景描述一下的话,应该是这样的. 项目经理:今天我们正式开始一个新项目,iOSer你负责把苹果端的APP完成,有没有问 ...
- 学习笔记:Tab Bar 控件使用详解
注意这里是:Tab Bar 不是Tab Bar Controller. Tab bar是继承UIView,所以可以添加到ViewController里.是View就可以add到另一个View上去.Ta ...