Mysql之索引优化案例
Mysql之索引优化案例
- 1.单表简单案例
- 1.1创建表
- 1.2 问题:
- 1.3 解决:新建索引
- 1.4 再次执行
- 2.双表简单案例
- 2.1创建表并插入数据
- 2.2 由于是LEFT JOIN,所以左表是主表,因此第一次索引尝试加在主表上
- 2.3继续改进
- 2.4 结论
- 3.三表简单案例
- 3.1添加一张表
- 3.2改进
- 3.3总结
1.单表简单案例
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` VARBINARY(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'),
(3,3,3,3,'3','3');
查询
查询category_id 为1且comments>1的情况下,观看数量最多的文章
explain select id,author_id from article where category_id = 1 and comments > 1 order by views desc limit 1 --分析sql
1.2 问题:
type:all,全表扫描,情况不容乐观
Using filesort:文件内排序,情况不容乐观*2
如何优化,查询表的索引
show index from article --查看表索引
1.3 解决:新建索引
ALTER TABLE article ADD INDEX idx_article_ccv (category_id, comments, views) --第一种方式
CREATE INDEX idx_article_ccv ON article (category_id, comments, views) --第二种方式
查看优化后结果
问题:
全表扫描已解决,但是文件排序依然存在
索引不合适
删除索引之后重新建立
DROP INDEX idx_article_ccv ON article -- 删除索引
CREATE INDEX idx_article_ccv ON article (category_id,views) --重建索引
1.4 再次执行
完美解决
2.双表简单案例
2.1创建表并插入数据
CREATE TABLE IF NOT EXISTS `class`(
`id` INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
`card` INT (10) UNSIGNED NOT NULL
);
CREATE TABLE IF NOT EXISTS `book`(
`bookid` INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
`card` INT (10) UNSIGNED NOT NULL
);
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO class(card)VALUES(FLOOR(1+(RAND()*20)));INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO book(card)VALUES(FLOOR(1+(RAND()*20)));
explain显示执行计划
EXPLAIN SELECT * from class LEFT JOIN book ON class.card = book.card
2.2 由于是LEFT JOIN,所以左表是主表,因此第一次索引尝试加在主表上
- 只对左表class新增索引
CREATE INDEX idx_class_card ON class (card)
EXPLAIN SELECT * from class LEFT JOIN book ON class.card = book.card
结果:
虽然type变为index,但是扫描行数依然是全表扫描。
2.3继续改进
- 只对右表book 新增索引
DROP INDEX idx_class_card on class --删除class表索引
CREATE INDEX idx_book_card ON book (card)
EXPLAIN SELECT * from class LEFT JOIN book ON class.card = book.card
结果:type变为ref,rows只扫描了一行。
2.4 结论
这是由于LEFT JOIN特性决定的,由于左表数据全都有,所以关键在于如何从右表进行搜索,所以右表一定要添加索引。
3.三表简单案例
3.1添加一张表
- 在双表的基础上新增一张phone表
CREATE TABLE IF NOT EXISTS `phone`(
`phoneid` INT(10) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
`card` INT (10) UNSIGNED NOT NULL
)ENGINE = INNODB;INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
INSERT INTO phone(card)VALUES(FLOOR(1+(RAND()*20)));
注意:三表均没有新建索引
执行计划
EXPLAIN SELECT * from class LEFT JOIN book ON class.card = book.card LEFT JOIN phone ON book.card = phone.card
结果: 全表扫描,且使用了连接缓存
3.2改进
- 在phone和book表新增索引
CREATE INDEX idx_phone_card ON phone(card)
CREATE INDEX idx_book_card ON book (card)
EXPLAIN SELECT * from class LEFT JOIN book ON class.card = book.card LEFT JOIN phone ON book.card = phone.card
3.3总结
- 语句优化应尽可能减少join语句中NestedLoop的循环总次数,即“永远用小结果集驱动大结果集”。
优先优化NestedLoop的内层循环。 - 尽量保证join语句中被驱动表的条件字段添加了索引(即LEFT JOIN在右表上添加,反之亦然)。
- 当无法保证被驱动表的条件字段添加索引时,且内存资源充足的前提下,不妨调整join
buffer以达到性能优化的目的。
Mysql之索引优化案例相关推荐
- 知识点:Mysql 数据库索引优化实战(4)
知识点:Mysql 索引原理完全手册(1) 知识点:Mysql 索引原理完全手册(2) 知识点:Mysql 索引优化实战(3) 知识点:Mysql 数据库索引优化实战(4) 一:插入订单 业务逻辑:插 ...
- MySQL - 索引优化案例实操
文章目录 生猛干货 DB Version Table Case 1 : 联合索引第一个字段用范围不一定会走索引 优化一 强制走索引 force index(idx_name_age_position) ...
- MySQL的单表索引优化案例
创建数据表及插入数据 create table if not exists article(id int(10) unsigned not null primary key auto_incremen ...
- mysql半连接_MySQL优化案例:半连接(semi join)优化方式导致的查询性能低下(转载)...
以下是来自DBA+社群MySQL领域原创专家李海翔分享的MySQL优化案例,关于MySQL V5.6.x/5.7.x SQL查询性能问题. 一.简单创建一表,并使用存储过程插入一部分数据 二.执行如下 ...
- Mysql高级 索引优化
Mysql逻辑架构 Mysql与其他数据库相比有点与众不同,他的架构可以在多种不同的场景中应用并发挥作用,主要体现在存储引擎的架构上,插件式的存储引擎结构将查询处理和其他的系统任务以及数据的存储提取分 ...
- MySQL高级-索引优化(超详细)
性能分析 MySQL Query Optimizer Mysql中由专门负责优化SELECT语句的优化器,主要功能就是通过计算分析系统中收集到的统计信息,为客户端请求的Query提供他认为最优的执行计 ...
- MySQL基础: 索引, 优化, 锁
一. mysql的架构介绍 从几年前实习开始, 陆陆续续写了好多的markdown笔记, 早期的笔记大多是在B站和一些大牛博客分享而自己整理的笔记, 早期的笔记体系比较清晰,也是我的学习成长路线. ...
- MySQL - 践行索引优化
文章目录 生猛干货 Pre Table Demo DB Version Case 全值匹配 最左前缀 禁止索引列上做任何操作(计算.函数.(自动or手动)类型转换) 存储引擎不能使用索引中范围条件右边 ...
- mysql 字符串索引 优化_MySQL性能优化之索引调优实战
索引失效场景或使用注意事项 a.索引无法存储null值,所以建议都给默认值 b.如果条件中有or,即使使用了索引条件也不起作用,所以尽量少用or 如果想使用or,又让索引生效,只能将or的每个列上加上 ...
最新文章
- java中String对象和String变量
- 究竟使用什么样的万向轮?
- Kafka解惑之Old Producer(4)——Case Analysis
- FLEX:target和currentTarget属性的区别
- 集合中的实体类根据一个字段合并_JAVA中序列化与反序列化
- 2008安装完了找不到_7206BEP.进口轴承_玉溪SKF轴承安装指南
- 手机端整张显示出来_现在动辄就4500万像素,像素越高显示效果真的越好吗?...
- 基于bitbucket中央库的Git操作
- 魔术师利用一副牌中的13张红桃c语言,魔术师的猜牌术(1) 魔术师利用一副牌中的13张黑桃 - 下载 - 搜珍网...
- SQLServer2012 查询分析器的快捷键
- 深入学习理解UNIX网络编程
- 求定积分sinx的c语言编程,sinx定积分计算
- PPT设置自动保存时间 mac_如何让你的PPT变得高大上?
- 40 个科研学术网站,赶紧来收藏一波!
- spring data JPA的使用
- Bmob后端云——Android再也不担心没有后台了
- Tyrion (含示例源码)
- seo日常工作表_seo专员日常工作内容是什么?
- 修改文件扩展名(只需四步)
- 我当测试总监的那几年 | 程序员有话说