[MySQL性能优化系列] 聚合索引
1. 普通青年的索引使用方式
假设我们有一个用户表 tb_user,内容如下:
name | age | sex |
---|---|---|
jack | 22 | 男 |
rose | 21 | 女 |
tom | 20 | 男 |
... | ... | ... |
执行SQL语句:
SELECT name FROM tb_user WHERE age = 20;
默认情况下,MySQL需要遍历整张表,才能找到符合条件的记录。如果在age字段上建立索引,那么MySQL可以很快找到所有符合条件的记录(索引本身通过B+树实现,查起来很快。简单起见,想象一下二分查找和遍历查找的区别。)
2. 文艺青年的玩法
2.1 用冗余的联合索引加速查询
接着上面的例子,我们假设,tb_user表有一百万行,通常情况下,"WHERE age = 20"这样的语句,会返回几万行数据,实际测试下发现,速度不够快。
原因是,MySQL根据索引查询到符合条件的记录后,还需要到表空间里一一查找这些记录(实际上,索引里同时记录了age字段和关联记录的物理行号),这意味着,MySQL必须读取表空间多达几万次,才能返回最终结果。
聪明的你可能已经想到了,如果age字段的索引上有name字段的值话,MySQL就不用再费事地去访问表空间了。
最终解决方案:建立联合索引,让MySQL直接从索引中取出name字段的值
KEY `age_with_name` (`age`,`name`)
注意这里的顺序,必须是先age后name,反之不行(除非你是根据name查age)。
2.2 用冗余的联合索引加速排序
依然是之前的表,假设要做这样的查询:
SELECT * FROM tb_user ORDER BY age;
因为我们在age上有索引,所以排序是很快的(索引的本质就是将表记录的物理行号按照特定规则排序)
实际项目中,SQL可能比这个复杂些,比如:
SELECT * FROM tb_user WHERE sex='男' ORDER BY age;
这个时候,age字段上的索引就派不上用场了。因为,age索引是面向整个表的,筛选后的表和age索引是对不上的。
解决方案:依然是联合索引!
KEY `age_with_name` (`sex`,`age`)
这个联合索引,同时记录了sex和age,并且排序的规则是,先按sex排,sex相同时按age排。那么,通过"WHERE sex='男'",MySQL先对索引进行筛选,然后剩下的索引正好就是按照age排序的了。因此,整个SQL的排序速度依然很快。
最新文章
- checkbox做全选按钮
- Android学习杂记
- onclick传递参数
- 【VLC-Android】LibVLC API简介(相当于VLC的MediaPlayer)
- 链表操作,空间复杂度要求为O(1)
- gson使用详解
- [Angular + Webpack] ocLazyLoad compoment
- 3. SQL Server数据库状态监控 - 可用空间
- 【20171025晚】alert(1) to win 第五题 正则表达式过滤
- CentOS7部分调优命令
- mysql新增用户并开启远程连接
- OpenVDB for Mitsuba
- 图片的滑动缩放html、css、js代码
- java.lang.OutOfMemoryError及解决方案
- 【Python】【一些概念与对比】
- Orchard 前台权限与自定义权限
- jQuery源码分析-构造函数详解
- 基于Android应用《玩转英语》(总报告)
- 申请Let's Encrypt通配符HTTPS证书
- sqlserver年月日转汉字大写
热门文章
- springMVC_06数据的处理
- Java中net.sf.json包关于JSON与对象互转的坑
- C#设计模式之十一享元模式(Flyweight Pattern)【结构型】
- 在Java中进行序列化和反序列化
- Vue项目build打包部署到Tomcat后,刷新报404错误解决方案
- JavaScript是如何工作的:Web Workers的构建块 + 5个使用他们的场景
- crontab架构和格式
- 洛谷P4593 [TJOI2018]教科书般的亵渎(拉格朗日插值)
- 判断NaN的真假
- Android为TV端助力 事件分发机制