当面试官问你mysql优化时..

文章部分引用自 链接

用like模糊查询不要用 ‘%’ 开头

数据库引擎会放弃索引进行全表扫描,如果不是必要,尽量别这么干

select id from user where name like '%codeMan%'    //×

不要动不动就select *

如果你要的只是用户名,为啥你要用*呢,不要返回用不到的任何字段,万一用户的属性有几十行,你只是想要个用户名,何必呢。又耗性能、又不能使用到覆盖索引

select * from user 	// ×
select user_name from user // √

别动不动就全表扫描

考虑在where和order by涉及的列加索引

不要在where对字段进行null判断

数据库引擎会放弃索引进行全表扫描,如果不是必要,尽量别这么干
换句话说,你可以用0来代替null,索引 NULL 列需要额外的空间来保存,所以要占用更多的空间

进行比较和计算时要对 NULL 值做特别的处理

不要在where子句用!或者>、<操作符

数据库引擎会放弃索引进行全表扫描

不要在where里面写字段表达式

数据库引擎会放弃索引进行全表扫描

select id from user where money / 10 = 10

你不能这样写么?

select id from user where money = 10 * 10

都给我弄到 “ = ” 右边去

不要在where子句用函数操作

select id form user where substring(user_name,1,4)='code' //×

给我这样写

select id from user where user_name like 'code%'

不要用in和not in

数据库引擎会放弃索引进行全表扫描,如果是连续数值,你可以用between;如果是子查询,你可以用exists,很多时候用exists代替in是一个好选择

不要在where子句使用or

数据库引擎会放弃索引进行全表扫描

select id from user where money = 50 or money = 100 //×

给我这样写

select id from user where money = 50 union all select id from user where money = 100

避免使用子查询,可以把子查询优化为 join 操作

通常子查询在 in 子句中,且子查询中为简单 SQL(不包含 union、group by、order by、limit 从句) 时,才可以把子查询转化为关联查询进行优化。

子查询性能差的原因:

子查询的结果集无法使用索引,通常子查询的结果集会被存储到临时表中,不论是内存临时表还是磁盘临时表都不会存在索引,所以查询性能会受到一定的影响。特别是对于返回结果集比较大的子查询,其对查询性能的影响也就越大。

由于子查询会产生大量的临时表也没有索引,所以会消耗过多的 CPU 和 IO 资源,产生大量的慢查询。

索引

如果索引是复合索引,必须使用该索引中的第一个字段作为条件

这样才能保证系统使用该索引,否则该索引将不会被使用,并且应尽可能的让字段顺序与索引顺序相一致
所以,我们要把区分度高、长度小、使用最频繁的放在联合索引的最左侧

数据量小的表不需要建立索引
不经常用的列不需要加索引
对于重复多的数据,不要去建索引。

SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,比如表中有个字段sex,只有男和女,有必要去建索引吗?没有,这样反而适得其反。

索引是不是越多约好?

数据变更需要维护索引,因此更多的索引意味着更多的维护成本。
更多的索引意味着更多的存储空间。
索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率, 因为 insert 或 update 时有可能会重建索引,因为 MySQL 优化器在选择如何优化查询时,会根据统一信息,对每一个可以用到的索引来进行评估,以生成出一个最好的执行计划,如果同时有很多个索引都可以用于查询,就会增加 MySQL 优化器生成执行计划的时间,同样会降低查询性能。
据说有个潜规则:单张表索引不超过 5 个

对于频繁的查询优先考虑使用覆盖索引

覆盖索引:就是包含了所有查询字段 (where,select,ordery by,group by 包含的字段) 的索引

  • 避免 Innodb 表进行索引的二次查询: Innodb 是以聚集索引的顺序来存储的,对于 Innodb来说,二级索引在叶子节点中所保存的是行的主键信息,如果是用二级索引查询数据的话,在查找到相应的键值后,还要通过主键进行二次查询才能获取我们真实所需要的数据。而在覆盖索引中,二级索引的键值中可以获取所有的数据,避免了对主键的二次查询,减少了 IO 操作,提升了查询效率。
  • 可以把随机 IO 变成顺序 IO 加快查询效率: 由于覆盖索引是按键值的顺序存储的,对于 IO密集型的范围查找来说,对比随机从磁盘读取每一行的数据 IO 要少的多,因此利用覆盖索引在访问时也可以把磁盘的随机读取的 IO转变成索引查找的顺序 IO。

尽量避免使用外键约束

  • 不建议使用外键约束(foreign key),但一定要在表与表之间的关联键上建立索引
  • 外键可用于保证数据的参照完整性,但建议在业务端实现
  • 外键会影响父表和子表的写操作从而降低性能

能用数字型字段表示尽量用数字型字段

尽量用varchar代替char

varchar是变长字段,可以节省存储空间,搜索效率高

关于游标

尽量不要使用游标,效率较差

不要在数据库存图片、文件等大的二进制数据

通常我们存在服务器,或者调用像七牛云的API存储大二进制文件,数据库保存获取文件的链接即可

在明显不会有重复值时使用 UNION ALL 而不是 UNION

  • UNION 会把两个结果集的所有数据放到临时表中后再进行去重操作
  • UNION ALL 不会再对结果集进行去重操作

尽量使用预编译

既减少了sql编译的所需时间,又解决了sql注入的问题
ps:
关于索引的深入,可以深入浅出看看这两篇文章,都是转载自极客的一位老师写的,觉得写的很好~
索引1
索引2

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值