【转】Mysql索引设计原则
来源:https://segmentfault.com/a/1190000000473085
假设一高频查询如下
SELECT * FROM user WHERE area='amoy' AND sex=0 ORDER BY last_login DESC limit 30;
如何建立索引?描述考虑的过程
user表如下:
初始化100W条数据,其中,area要通过IP查询生成,sex为 0,1 随机
CREATE TABLE user
(id
int(10) NOT NULL AUTO_INCREMENT COMMENT '自增编号',username
varchar(30) NOT NULL DEFAULT '0' COMMENT '用户名',password
varchar(30) NOT NULL DEFAULT '0' COMMENT '密码',area
varchar(30) NOT NULL COMMENT '地址',sex
int(10) NOT NULL COMMENT '性别1,男;2,女。',last_login
int(10) NOT NULL COMMENT '最近一次登录时间戳',
PRIMARY KEY (id
)
) ENGINE=InnoDB AUTO_INCREMENT=892013 DEFAULT CHARSET=latin1
最终我的索引
(last_login,area)
索引原则:
1.where和order by等的字段建立索引
2.使用唯一索引:对于last_login,area等字段重复的次数比较少,可以使用索引;而sex无非就两个值:性别1,男;2,不值得索引
3.多列索引:不要为每一个列单独建立索引,这样并不能将mysql索引的效率最大化。使用“索引合并策略”
4.选择合理的索引列顺序:索引列的顺序意味着索引首先按照最左列进行排序,然后是第二列,以此类推。如(last_login,area)会先按照 last_login 进行排序,然后才是area。
5.将选择性最高的索引放到前面,也就是会所按照这个条件搜索到的数据最少,选择性就越高,比如选择性:last_login> area> sex。
6.索引不是越多越好,适合的索引可以提高查询效率,但是会降低写入效率,根据项目保持两者的平衡性最好了。
总结上面,首先sex不适合建立索引,有没有索引对于效率的提升意义不大,其次索引会按照最左列进行排序,因此将last_login放到最前面。
测试过程:
user表
没有任何索引的查询相关日志:
SELECT * FROM user WHERE area='美国ATT用户' AND sex=0 ORDER BY last_login DESC limit 30; 0.57s
SELECT * FROM user WHERE area='泰国' AND sex=0 ORDER BY last_login DESC limit 30; 0.56s
SELECT * FROM user WHERE area='台湾省台湾大宽频' AND sex=0 ORDER BY last_login DESC limit 30; 0.55s
SELECT * FROM user WHERE area='美国弗吉尼亚州' AND sex=0 ORDER BY last_login DESC limit 30; 0.59s
SELECT * FROM user WHERE area='德国奔驰汽车' AND sex=0 ORDER BY last_login DESC limit 30; 0.55s
SELECT * FROM user WHERE area='台湾省中华电信' AND sex=0 ORDER BY last_login DESC limit 30; 0.55s
SELECT * FROM user WHERE area='韩国' AND sex=0 ORDER BY last_login DESC limit 30; 0.57s
SELECT * FROM user WHERE area='拉美地区' AND sex=0 ORDER BY last_login DESC limit 30; 0.58s
SELECT * FROM user WHERE area='美国纽约(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.57s
SELECT * FROM user WHERE area='印度尼西亚' AND sex=0 ORDER BY last_login DESC limit 30; 0.57s
共花费时间:5.66s
建立索引area:
ALTER TABLE user
ADD INDEX index_area
(area
) ;
SELECT * FROM user WHERE area='美国ATT用户' AND sex=0 ORDER BY last_login DESC limit 30; 0.06s
SELECT * FROM user WHERE area='泰国' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='台湾省台湾大宽频' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='美国弗吉尼亚州' AND sex=0 ORDER BY last_login DESC limit 30; 0.10s
SELECT * FROM user WHERE area='德国奔驰汽车' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
SELECT * FROM user WHERE area='台湾省中华电信' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='韩国' AND sex=0 ORDER BY last_login DESC limit 30; 0.11s
SELECT * FROM user WHERE area='拉美地区' AND sex=0 ORDER BY last_login DESC limit 30; 0.20s
SELECT * FROM user WHERE area='美国纽约(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.07s
SELECT * FROM user WHERE area='印度尼西亚' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
共花费时间:0.66s
可见,建立area以后对性能的影响是巨大的(5.66/0.66 约为8.5758倍)
删除索引:ALTER TABLE user
DROP INDEX index_area
;
删除area索引发现时间又变成了0.57s
建立last_login索引:
SELECT * FROM user WHERE area='美国ATT用户' AND sex=0 ORDER BY last_login DESC limit 30; 0.03s
SELECT * FROM user WHERE area='泰国' AND sex=0 ORDER BY last_login DESC limit 30; 0.09s
SELECT * FROM user WHERE area='台湾省台湾大宽频' AND sex=0 ORDER BY last_login DESC limit 30; 0.51s
SELECT * FROM user WHERE area='美国弗吉尼亚州' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='德国奔驰汽车' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
SELECT * FROM user WHERE area='台湾省中华电信' AND sex=0 ORDER BY last_login DESC limit 30; 0.07s
SELECT * FROM user WHERE area='韩国' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='拉美地区' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='美国纽约(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
SELECT * FROM user WHERE area='印度尼西亚' AND sex=0 ORDER BY last_login DESC limit 30; 0.06s
共花费时间:0.87s
同样能够提升性能(5.66/0.87 约为6.5057倍)
建立sex索引:
ALTER TABLE user
ADD INDEX index_sex
(sex
) ;
SELECT * FROM user WHERE area='美国ATT用户' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
SELECT * FROM user WHERE area='泰国' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
SELECT * FROM user WHERE area='台湾省台湾大宽频' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
SELECT * FROM user WHERE area='美国弗吉尼亚州' AND sex=0 ORDER BY last_login DESC limit 30; 0.89s
SELECT * FROM user WHERE area='德国奔驰汽车' AND sex=0 ORDER BY last_login DESC limit 30; 0.88s
SELECT * FROM user WHERE area='台湾省中华电信' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
SELECT * FROM user WHERE area='韩国' AND sex=0 ORDER BY last_login DESC limit 30; 0.86s
SELECT * FROM user WHERE area='拉美地区' AND sex=0 ORDER BY last_login DESC limit 30; 0.88s
SELECT * FROM user WHERE area='美国纽约(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
SELECT * FROM user WHERE area='印度尼西亚' AND sex=0 ORDER BY last_login DESC limit 30; 0.87s
共花费时间:8.73s
同样能够提升性能(5.66s/8.73 约为0.6483倍)效率反而降低了??求解?
建立这个sex索引还不如不建。
删除索引:
ALTER TABLE user
DROP INDEX index_sex
;
发现时间又变成了0.57s左右,
建立两个单独的索引:
ALTER TABLE user
ADD INDEX index_area
(area
) ,
ADD INDEX index_last_login
(last_login
) ;
SELECT * FROM user WHERE area='美国ATT用户' AND sex=0 ORDER BY last_login DESC limit 30; 0.09s
SELECT * FROM user WHERE area='泰国' AND sex=0 ORDER BY last_login DESC limit 30; 0.33s
SELECT * FROM user WHERE area='台湾省台湾大宽频' AND sex=0 ORDER BY last_login DESC limit 30; 0.21s
SELECT * FROM user WHERE area='美国弗吉尼亚州' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='德国奔驰汽车' AND sex=0 ORDER BY last_login DESC limit 30; 0.28s
SELECT * FROM user WHERE area='台湾省中华电信' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='韩国' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='拉美地区' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='美国纽约(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.03s
SELECT * FROM user WHERE area='印度尼西亚' AND sex=0 ORDER BY last_login DESC limit 30; 0.67s
发现建立两个单独的索引还不如只建立一个索引
删除索引:
发现时间又变成了0.57s左右,
建立一个的联合索引:
ALTER TABLE user
ADD INDEX index_last_login_area
(last_login
,area
) ,
SELECT * FROM user WHERE area='美国ATT用户' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='泰国' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='台湾省台湾大宽频' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='美国弗吉尼亚州' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='德国奔驰汽车' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='台湾省中华电信' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='韩国' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='拉美地区' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='美国纽约(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
SELECT * FROM user WHERE area='印度尼西亚' AND sex=0 ORDER BY last_login DESC limit 30; 0.00s
额,第二条数据这是怎么了,我测试了5次都在这附近晃悠哈!
这尼玛,找对索引啦!就该这么建立,查询不出来需要的时间啦!估计就是我们需要的索引啦!!!!
删除索引:
发现时间又变成了0.57s左右,
建立一个的联合索引:
ALTER TABLE user
ADD INDEX index_sex_last_login_area
(sex
,last_login
,area
)
SELECT * FROM user WHERE area='美国ATT用户' AND sex=0 ORDER BY last_login DESC limit 30; 0.18s
SELECT * FROM user WHERE area='泰国' AND sex=0 ORDER BY last_login DESC limit 30; 0.17s
SELECT * FROM user WHERE area='台湾省台湾大宽频' AND sex=0 ORDER BY last_login DESC limit 30; 0.81s
SELECT * FROM user WHERE area='美国弗吉尼亚州' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='德国奔驰汽车' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='台湾省中华电信' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
SELECT * FROM user WHERE area='韩国' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='拉美地区' AND sex=0 ORDER BY last_login DESC limit 30; 0.01s
SELECT * FROM user WHERE area='美国纽约(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.03s
SELECT * FROM user WHERE area='印度尼西亚' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
sex怎么总是你在拖后腿啊!把你调整到索引的最后一个吧!
删除索引:
发现时间又变成了0.57s左右,
建立一个的联合索引:
ALTER TABLE user
ADD INDEX index_last_login_area_sex
(area
,last_login
,sex
)
SELECT * FROM user WHERE area='美国ATT用户' AND sex=0 ORDER BY last_login DESC limit 30; 0.03s
SELECT * FROM user WHERE area='泰国' AND sex=0 ORDER BY last_login DESC limit 30; 0.07s
SELECT * FROM user WHERE area='台湾省台湾大宽频' AND sex=0 ORDER BY last_login DESC limit 30; 0.50s
SELECT * FROM user WHERE area='美国弗吉尼亚州' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='德国奔驰汽车' AND sex=0 ORDER BY last_login DESC limit 30; 0.05s
SELECT * FROM user WHERE area='台湾省中华电信' AND sex=0 ORDER BY last_login DESC limit 30; 0.06s
SELECT * FROM user WHERE area='韩国' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='拉美地区' AND sex=0 ORDER BY last_login DESC limit 30; 0.02s
SELECT * FROM user WHERE area='美国纽约(Prudential)' AND sex=0 ORDER BY last_login DESC limit 30; 0.04s
SELECT * FROM user WHERE area='印度尼西亚' AND sex=0 ORDER BY last_login DESC limit 30; 0.06s
综上所述:1.建立索引不一定能够加快查询效率如sex这种给重复次数特别多的列增加索引如sex这种会降低查询效率,具体的原因有待查找
2.给重复次数比较少的列增加u讴吟还是能够大幅度提高效率
3.给where和orderby之后的字段添加索引才会加快查询效率
4.为每一个列单独建立索引,不能将索引的效率最大化,应该使用索引合并策略,即根据查询条件,建立联合索引
5.联合索引的顺序问题:将选择性高的索引放到前面
6.根据资料建立索引意味着索引按照最左列进行排序,然后事第二列,以此类推。如(last_login ,area)就会按照last_login进行排序,然后才是area
7.根据这次的这个查询条件来说最好的索引是:ALTER TABLE user
ADD INDEX index_last_login_area
(last_login
,area
)。
【转】Mysql索引设计原则的更多相关文章
- MySQL三层结构、用户权限、索引设计原则
一.守护进程是什么? Linux Daemon(守护进程)是运行在后台的一种特殊进程.它独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件.它不需要用户输入就能运行而且提供某种服务,不是对 ...
- mysql的索引设计原则以及常见索引的区别
索引定义:是一个单独的,存储在磁盘上的数据库结构,其包含着对数据表里所有记录的引用指针. 数据库索引的设计原则: 为了使索引的使用效率更高,在创建索引时,必须考虑在哪些字段上创建索引和创建什么类型的索 ...
- MySql 表索引设计原则
索引的优点 1.加快数据的检索速度,这是创建索引的最主要的原因; 2.通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性; 3.加速表和表之间的连接; 4.在使用分组和排序子句进行数据检索时,可 ...
- Mysql高级操作学习笔记:索引结构、树的区别、索引优缺点、创建索引原则(我们对哪种数据创建索引)、索引分类、Sql性能分析、索引使用、索引失效、索引设计原则
Mysql高级操作 索引概述: 索引是高效获取数据的数据结构 索引结构: B+Tree() Hash(不支持范围查询,精准匹配效率极高) 树的区别: 二叉树:可能产生不平衡,顺序数据可能会出现链表结构 ...
- MySQL索引设计需要考虑哪些因素?
索引小知识 篇幅有限,索引的基本知识我们就不赘述了,在此,我们尝试说明其中的一个小点-----B+树与B树的区别到底是什么. InnoDB是使用B+树来实现其索引功能的.在B+树中,内节点(非叶子节点 ...
- mySql 数据库设计原则
mysql数据库设计原则: 必须使用InnoDB存储引擎 解读:支持事务.行级锁.并发性能更好.CPU及内存缓存页优化使得资源利用率更高 禁止使用存储过程.视图.触发器.Event 解读:高并发大数据 ...
- mysql索引设计的注意事项
mysql索引设计的注意事项 目录 一.索引的重要性 二.执行计划上的重要关注点 (1).全表扫描,检索行数 (2).key,using index(覆盖索引) (3).通过key_len确定究竟使用 ...
- mysql索引设计的注意事项(大量示例,收藏再看)
mysql索引设计的注意事项(大量示例,收藏再看) 目录 一.索引的重要性 二.执行计划上的重要关注点 (1).全表扫描,检索行数 (2).key,using index(覆盖索引) (3).通过ke ...
- Sql Server系列:索引设计原则及优化
1. 索引设计原则 索引设计不合理或缺少索引都会对数据库的性能造成障碍,高效的索引对于获得良好的性能非常重要. 设计索引时的一些原则: ◊ 索引并不是越多越好,一个表中如果有大量的索引,不仅占用大量的 ...
随机推荐
- 汉诺塔III
题目描述: 约19世纪末,在欧州的商店中出售一种智力玩具,在一块铜板上有三根杆,最左边的杆上自上而下.由小到大顺序串着由64个圆盘构成的塔.目的是将最左边杆上的盘全部移到右边的杆上,条件是一次只能移动 ...
- Springboot添加定时任务
请参考这篇文章:https://blog.csdn.net/ysp_0607/article/details/71430281
- Selenium-java测试环境搭建
1.1背景 Selenium也是一个用于Web应用程序测试的工具.Selenium测试直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE.Mozilla Firefox.Mozilla ...
- SDN 软件定义网络----学习1
原文地址https://www.infoq.cn/article/sdn-and-cloud-network 1.1,什么是 SDN? 什么是 SDN?SDN 的官方解释上提出了 SDN 的三个特性: ...
- Jenkins使用QQ邮箱构建邮件提醒服务
前置条件: 已安装好Jenkins服务端 步骤: 访问Jenkins服务端(ip+端口),登录Jenkins 点击系统管理 选择管理插件 选择可选插件 搜索Mailer Plugin 点击直接安装 点 ...
- vue 打印功能
printContent (e) { let subOutputRankPrint = document.getElementById('subOutputRank-print') console.l ...
- 使用Python画一个带坐标轴的圆
Download Microsoft Visual Studio Microsoft Visual Studio enables you develop your python Application ...
- Java 8 Lambda 表达式(二)
lambdas 实现 Runnable 接口 下面是使用 lambdas 来实现 Runnable 接口的示例: // 1.1使用匿名内部类 new Thread(new Runnable() { @ ...
- Anaconda安装(Windows)
Anaconda集成了python和各种常用工具. 目前有两个版本,分别包含了python2.7和python3.5,并且自动添加环境变量.去官网下载安装包. 1.安装其他模块.conda insta ...
- vue打包上传oss
今天把vue打包之后上传到oss,遇到了一点问题,现在解决了总结一下心得: OSS (Object Storage Service)名为对象存储,配合cdn使用达到静态文件托管加速,提升网站文件访问速 ...