mysql索引的使用和优化

参考

陈川大佬的博客
https://www.jianshu.com/p/d7665192aaaf

索引的类型

普通索引、唯一性索引、主键索引,也可以分为 主索引、辅助索引

  1. 普通索引的作用:
  • 条件查询: where id=1
  • 范围查询: where id<200, between and, in
  • 模糊后缀匹配查询: like 'hello%'
  • 排序: order by 重点注意:非主键的普通索引,如果查询的内容里面还有其他字段则不走索引,只查询索引字段的的话走索引
//对info创建索引,如果查询其他字段的话,就不走索引而是大表扫描
select * from class a  order BY  info  ;

//对info创建索引,如果只查询索引字段的话,就走索引,不需要查询主表了
select info from class a  order BY  info ;
  • 分组查询
  • 表和表关联查询: join 和 left join、right join的逻辑不通
  1. 唯一性索引:基于普通索引的结构,但是value值只能对应一个数据。唯一性索引查询的时候,也会很快。
  2. 主键索引:是唯一索引的特殊类型,主键不可为空,唯一索引可以为null,每张表只能有1个主键,而且InnoDB的主键索引是聚簇索引,范围查询特别快。

索引的使用规范

  • 禁止在频繁变更的表上添加索引
  • 删除不再使用的索引,同时要优化索引,避免重复功能的索引(单列索引和符合索引重复)
  • 联合索引应该把区分度更大的字段放前面,效果更好
  • Innodb 不建议使用过长的字段作为主键,因为是聚集式索引,其他索引会存储不压缩的主键
  • 最左匹配原则有2个含义:like匹配通配符不能在前面、联合索引顺序也是按照从左到右的顺序
  • 索引字段 查询条件中含有函数或表达式,索引无效:比如 emp_no -1=3, left(title,6)=‘huangz'
  • 少基数的字段不建议使用索引,性能提升不明显,同时要DML的时候要维护索引,空间和性能上浪费。比如男女字段,比例大约1:1,提升不明显,如果男女比率 1000:1,那么查询女的用户的时候,性能提升明显。
  • mysql一次查询只能使用一个索引。如果要对多个字段使用索引,建立复合索引。
  • 字符串使用短索引,可以提高查询速度和节省磁盘空间和I/O操作

limit的优化

其实limit的性能并不好,特别是在limit的初始值较大的时候,比如 limit10000,20, 默认会顺序扫描到10000下标的数据,然后再继续扫描20个数据返回。
所以优化的方案:

  1. 根据业务场景,可以尝试用范围查找替代 limit查找
    比如换成 where ID>10000 limit 20,这样如果ID是主键的话,或者是索引,那么只一共扫描20行的数据。
    但是下面2个SQL的查询结果可能并不一样,因为ID可能是不连续的
  1. 如果不能用范围查找来替代的话,可以利用 limit+覆盖索引 来降低IO的开销以及 扫描的行数
//性能最差
select * from test   limit 90000,5;

//性能稍微改善,因为只需要扫描 900005行的id,再根据获取到的id 去匹配5行的大表里面的全数据
select a.* from test a join (select id from test limit 90000,5) b on a.id=b.id;

//性能最佳,但是要求id必须连续才行
select * from test where id>90000 limit 5;

覆盖索引

ID为主键,name为辅助索引,所以 SQL2 SQL3可以使用覆盖索引,而SQL1 查询条件里面有 sex字段,所以只能走全表扫描
InnoDB的主键索引是聚簇索引。
直接在辅助索引上面获取(索引字段、主键字段)是不需要去主索引中读取数据,直接从 辅助索引里面获取就可以了

EXPLAIN select id,name,sex  from user order by name limit 1000,10;    //全表扫描 0.015秒
EXPLAIN select id           from user order by name limit 1000,10;   //索引1010行 0.001秒
EXPLAIN select name         from user order by name limit 1000,10;  //索引1010行 0.001秒

注意的坑

  1. 如果统计行数的话,count(*)比count(Column) 更好。第二个会统计所有该column不为null的总行数,会耗费更多的搜索资源。但是如果统计某列的值不为Null的总行数,必须要用第二种统计方法。

  2. 如果字段有表达式,那么就不会走索引,例如下面的 id+1=500,就会走全表扫描 ,但是值是支持表达式的,仍然会走索引

EXPLAIN select * from wx_ib where id+1=500; //不走索引
EXPLAIN select * from wx_ib where id=500-1; //使用索引

  1. 索引的选择
  • 小表不要建索引,全表扫描更快
  • 删除掉不常用的索引,因为每次DML都要维护索引
  • 避免创建重复的索引,比如表中已经有索引 Index(name),如果要添加联合索引的话,修改成Index(name,address),而不是再创建一个新的联合索引。
  • 超大型表的话,分区、分库可能是更好的选择,维护索引的成本太高了
  1. 海量数据的业务场景下情况下,反范式的冗余字段,来避免表和表之间的关联查询,可能更有效。比如学生表里面,包含了学生成绩,这样就不需要关联成绩表,但是更新成绩的时候,要同时更新 成绩表和学生表。

  2. 两张表做关联查询的时候:关联字段需要创建索引,提升效率
    join 和 left join、 right join不一样

join的时候: 在没有其他过滤条件的情况下MySQL会自动选择小表作为驱动表

  • 普通查询:只要在一张表上创建索引既可以,先后顺序无所谓(例如SQL1 和SQL2)
  • 关联查询+条件查询:两张表都创建关联字段的索引,这样查询的时候会走2个索引(例如SQL3)
-- SQL1
select * from class a join student_test b on a.info=b.info ;
-- SQL2
select * from student_test a join class b on a.info=b.info ;

-- SQL3
select * from class a join student_test b on a.info=b.info where a.info like '100_';

left join 或者 right join的时候,需要在从表上创建索引
例如下面的主表是 class表,那么需要在从表 student_test表的 info字段上创建相应的索引

select * from class a  left join student_test b on a.info=b.info ;
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,254评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,875评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,682评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,896评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,015评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,152评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,208评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,962评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,388评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,700评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,867评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,551评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,186评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,901评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,689评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,757评论 2 351

推荐阅读更多精彩内容