innoDB索引使用和优化汇总
2019独角兽企业重金招聘Python工程师标准>>>
一,索引类型
最常见的索引数据结构是B-Tree索引,按照顺序存储数据,所以mysql可以用来做order by和group by操作,应该数据是有序的,所以b-tree也就会将相关的列值都存储在一起。最后因为索引中存储实际的列值,某些查询只使用索引就可以完成全部查询。
单列索引
单一的一列索引
多列索引
如图,一个包含三列值的普通索引树
聚簇索引
不是一种单独的索引类型,而是一种数据存储方式,innoDB的聚簇索引实际上在同一结构中保存了B-Tree索引和数据行,当表有聚簇索引时,它的数据行实际上存放在索引的叶子页中,不是所有的存储引擎都支持聚簇索引。
聚簇索引和非聚簇索引对比图:
覆盖索引
如果一个索引包含或说覆盖所有需要查询的字段的值,成为覆盖索引
二,如何正确的使用索引?
索引依据
1、依据where查询条件建立索引
eg: select a,b from tb_test where c = ?; idx_c(c) ->正确select a,b from tb_test where c = ? and b = ? idx_cd(c,d) ->正确
2、根据排序order by ,group by , distinct 字段添加索引
eg: select * from tb_test order by a; select a,count(*) from tb_test group by a; idx_a(a) ->正确select * from tb_test order by a,b; idx_a_b(a,b) ->正确select * from tb_test order where c = ? by a; idx_c_a(c,a) ->正确
索引使用-最左前缀原理
例如,以表user中的a,b,c三个列建立联合索引
① 全列匹配: select * from user where a = ? and b =? and c = ?;
使用建立索引的三个列的值,精确使用到具体的索引,即使顺序不同mysql查询优化器会自动调整where语句的顺序(而不是innodb),使之适应索引结构
② 最左前缀匹配: select * from user where a = ? and b =? ;
没有提供完全的列值,索引是从左起进行连续匹配的,因此也能够使用利用a,b,c三列建立起来的索引。
③ 使用索引精确匹配,中间某个条件未提供。Select * from user where a = ? and c =? ;
虽然a和c都在索引列中,但是因为b不存在,所以无法匹配最左前缀的连接。
解决办法:1,如果有大量的查询通过这种方式进行,可以考虑在a和c列上建立一个联合索引。2,通过填坑的方式,即如果b列上的值不多的话(例如枚举,或者简单的bit类型),通过将sql优化成 select * from user where a = ? and b in(?,?,?……) and c = ? 的方式能够提升一部分的性能。
④ 查询没有使用到索引第一列 select * from user where b = ? and c = ?;
这种情况是不符合最左前缀的,无法使用该索引。
⑤ 匹配字符串前缀情况 select * from user where a = ? and b= ? and c like ‘abc%’;
这种情况符合最左前缀,可以使用索引,但如果通配符("_" "%"等)不是出现在末尾,则无法使用。
⑥ 范围查询 select * from user where a > ? and b = ? and c = ?;
这种情况能够使用索引,但是b和c列的索引无法使用到,如果范围查询不是最左前缀或者查询条件中有两个范围列则无法使用。
idx_ab(a,b)为例:
能使用上述索引进行排序的操作是:
order by a; a = 3 order by b; order by a,b; order by a desc ,b desc; a > 5 order by a;
不能使用索引帮助排序的查询
order by b; #没有使用到联合索引的第一个字段a > 5 order by b; #一旦前缀操作是一个range而非=操作,那么就无法利用到索引, 这里 a>5无法利用索引,二联合索引的第一个字段未利用, 因此 order by b也无法利用索引查询a in (1,3) order by b; #in里面的值没有建立索引,因此无法利用索引,a未用因此order by b也无法使用order by a asc, b desc; #这里order by a esc是利用了索引,但是b desc未利用到,因为b要和a排序方式一致才可利用到索引
⑦ 条件中带有函数或者表达式select * from user where a = ? and b = ? and left(c,2) = ‘ba’
虽然和c like ‘ba%’;达到的效果是一致的,但是由于使用了函数,因此无法使用索引。
对于使用了表达式的sql,例如 select * from user where a = ? and b = ? and c -1 =?;无法使用索引。
⑧ 字段类型不匹配,可能会导致无法使用索引 a int(11) ,idx_a(a)
where a = '123' ->错误,可能导致未知的错误,这个跟编码有关系
where a = 123 ->正确
三,哪些字段适合创建索引?
1、字段值的重复程度
如身份证号码基本上不可能重复,因此选择性非常好,而人的名字重复性较低,选择性也不错, 性别(男/女)选择性较差,重复度非常高
2、选择性很差的字段通常不适合创建索引,但也有例外
如:男女比例相仿的表中,性别不适合创建单列索引,如果走索引不如走全表扫描,因为走索引的I/O开销更大但如果男女比例极度不平衡,要查询的又是少数方,如:理工学校、IT公司等可以考虑使用索引
3、联合索引中选择性好的字段应该排在前面
select * from tab_a where gender=? and name=? idx_name_gender(name,gender) ->正确
4、联合索引可以为单列、复列查询提供帮助
idx_smp(a,b,c) where a=?; ->正确 where a=? and b=?; ->正确 where a=? and c=?; ->正确 (注:需要MySQL5.6版本以上;在5.5及以前版本,可以对a字段进行索引扫描,但c字段不行 ) where a=? and b=? and c=? ->正确
5、合理创建联合索引,避免冗余
(a),(a,b),(a,b,c) ->不可取 (a,b,c) ->正确,可以覆盖前两个
6,合理使用覆盖索引
对于最核心的SQL,我们可以考虑使用索引覆盖,查询用户名这种操作频率非常高,而索引里面又存储了字段的值,查询时,name字段的值直接在索引中返回,而不需要回表。
覆盖索引覆盖就是将你要查询的字段和条件字段一起建立联合索引,这样的好处是不需要回表获取name字段,IO最小,速度块
select name from tb_user where userid=? key idx_uid_name(userid,name) ->覆盖索引扫描
转载于:https://my.oschina.net/u/3152390/blog/812094
innoDB索引使用和优化汇总相关推荐
- MySQL InnoDB索引介绍及优化
转载自 https://segmentfault.com/a/1190000007445807 一.索引概念 索引(index)翻译为一个目录,用于快速定位我们想要找的数据的位置.例如:我们把一个数据 ...
- 【MySQL优化(六)】InnoDB索引优化与索引规约
序 上一篇讲解了建表规范后,本章重点分析下创建索引的一些规范 由于索引是工作在存储引擎层,所以以下规约都是基于InnoDB引擎 题外话 在满足语句需求的情况下, 尽量少地访问/消耗资源是数据库设计的重 ...
- 高并发之存储篇:关注下索引原理和优化吧!躲得过实践,躲不过面试官!
以MySQL的InnoDB索引为主,看完需要5分钟 本文内容预览: 为什么Kafka不需要我们关心索引,而Mysql却需要? Mysql数据怎么被组织 2.1 数据记录最小单位:行 2.2 与磁盘最小 ...
- Mysql 索引原理及优化
本文内容主要来源于互联网上主流文章,只是按照个人理解稍作整合,后面附有参考链接. 一.摘要 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引 ...
- MySQL 如何创建索引?怎么优化?
2019独角兽企业重金招聘Python工程师标准>>> 索引类似大学图书馆建书目索引,可以提高数据检索的效率,降低数据库的IO成本.MySQL在300万条记录左右性能开始逐渐下降,虽 ...
- MySQL-索引优化篇(2)_使用索引扫描来优化排序
文章目录 生猛干货 官方文档 使用索引扫描来优化排序 索引的列顺序和Order By子句的顺序完全一致 索引中所有列的方向(升序.降序)和 order by子句完全相同 order by中的字段全部在 ...
- Mysql InnoDB索引分析
索引介绍 在 MySQL 中,索引是在存储引擎层实现的,所以并没有统一的索引标准,即不同存储引擎的索引的工作方式并不一样.而即使多个存储引擎支持同一种类型的索引,其底层的实现也可能不同.InnoDB ...
- mysql 重复率高字段 索引_MySQL性能优化(二)索引优化
一.选择合适的列建立索引 1.在where从句,group by从句,order by从句,on从句中出现的列(select) 2.索引字段越小越好(表每页数据才会更多,IO效率会更高) 3.离散度大 ...
- 【MySQl】MyISAM和InnoDB索引对比
[MySQl]MyISAM和InnoDB索引对比 部分内容转自:http://www.2cto.com/database/201211/172380.html 比较好的文章:http://www.cn ...
最新文章
- 第5次作业+105032014166+张珍珍
- 月薪3000到年薪30万,你可知“千里之行始于Python”?
- ASP.NET专题研究——角色和Profile
- JNI之C语言简单回顾
- maf中anglearc_Oracle MAF中的LOV
- Docker从入门到实战(四)
- Apple’s current market value is more than two trillion
- element ui 弹出组件的遮罩层在弹出层的上面的解决方法
- asp.net MVC之 自定义过滤器(Filter)
- 【vijos】P1190 繁忙的都市
- Redis实战篇(视频学习来自黑马程序员)
- java代码性能优化实例
- 【paper 学习】1、DeepWiFi: Cognitive WiFi with Deep Learning
- python爬取南京市房价_Python的scrapy之爬取链家网房价信息并保存到本地
- 人脑与计算机类比文献,类比推理的影响因素和脑生理基础研究(刘昌2004).pdf
- Linux下的Html编辑器
- invoker 祈求者 c++ 题解
- 财务自由之路——我的投资史(2)
- linux上安装lftp
- 如何在 Mac 上愉快的使用 Docker
热门文章
- 在wordpress中使用 markdown:wp-markdown插件的使用方法
- presentViewController:navigationController animated:YES completion:^(void)
- 【操作系统】滨江学院 陈遥 期末试卷考点整理
- java方法被编译器调用_我异常了,快来捕获我,Java异常简述
- mysql闩_Oracle闩:Cache Buffers chains
- linux定时任务生效_Linux 添加定时任务
- java获取redis中各种数据类型key对应的value代码简单封装
- 怎么让Excel按某一列的数值来排序?
- mysql之delete删除记录后数据库大小不变
- JUnit 5 Alpha版本简化了单元测试