mysql in查询不要去重_MySQL 查询优化

本文介绍了MySQL查询优化的各种策略,包括使用索引的原则,如全值匹配、最左前缀法则,避免索引失效的操作,如计算和范围查询。还提到了LIKE查询、OR操作和NULL值对索引的影响,以及LEFT JOIN、INNER JOIN和STRAIGHT_JOIN的使用。此外,还讨论了排序、分组、子查询和分页优化,强调了去重查询的高效方法,并给出了EXISTS与IN的使用建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用索引

规则

全值匹配:查询的字段按照顺序在索引中都可以匹配到,

最佳左前缀法则:指的过滤条件要使用索引必须按照索引建立时的顺序依次满足 , 一旦跳过某个字段 , 索引后面的字段都无法被使用。

不在索引列上做计算:不在索引列上做任何操作(计算、函数、(自动 or 手动)类型转换「尤其注意 varchar 和 int」),会导致索引失效而转向全表扫描。

索引列上不能有范围查询:将可能做范围查询的字段的索引顺序放在最后

尽量使用覆盖索引:查询列和索引列一致,不写 select *;

不使用不等于(!=以及 <>)

当字段允许为 NULL 时:where 后条件 is null 可以使用索引,is not null 不可以用到索引

Like 以通配符(%sadfj%)开头时,MySQL 索引失效。解决办法:①可以使用主键索引;②使用覆盖索引,查询字段必须是建立覆盖索引字段;③当覆盖索引指向的字段是 varchar(380) 及 380 以上的字段时,覆盖索引会失效!

字符串不加单引号索引失效

少用 or,用了索引会失效

示例

236256826dda1b16b23ee74b611d534b.png

助记口诀

全职匹配我最爱,最左前缀要遵守;

带头大哥不能死,中间兄弟不能断;

索引列上少计算,范围之后全失效;

LIKE 百分写最右,覆盖索引不写*;

不等空值还有 OR,索引失效要注意;

VAR 引号不可丢,SQL 优化有诀窍。

具体方案

关联查询优化

LEFT JOIN:左侧为驱动表,右侧为被驱动表

INNER JOIN:MySQL 会自动将小结果的表作为驱动表

straight_join:效果和 inner join 一样,但是会强制将左侧作为驱动表!

子查询尽量不要放在被驱动表,有可能使用不到索引,会生成临时表。

在优化关联查询时,在被驱动表建立索引才有效。

排序优化

在索引列上

ORDER BY 语句使用索引最左前列

使用 WHERE 子句与 ORDER BY 子句条件列组合满足索引最左前列

ORDER BY 后字段同时使用升序或降序

如果 WHERE 使用索引的最左前缀为常量,则 OEDER BY 可以使用索引

ad7086e2c983cec5a60f57ca9c3cc80b.png

不在索引列上

双路排序:字面意思就是两次扫描磁盘,最终得到数据,读取行指针和orderby列,对他们进行排序,然后扫描已经排序好的列表,按照列表中的值重新从列表中读取对应的数据输出。

单路排序:从磁盘读取查询需要的所有列,按照order by列在buffer对它们进行排序,然后扫描排序后的列表进行输出,它的效率更快一些,避免了第二次读取数据。并且把随机IO变成了顺序IO,但是它会使用更多的空间,因为它把每一行都保存在内存中了。效率高

单路容易出现的问题:如果取出的数据总大小超过了 sort_buffer 的容量,导致每次只能取sort_buffer容量大小的数据,进行排序(创建tmp文件,多路合并),排完再取取sort_buffer容量大小,再排……从而多次I/O。

优化策略

① 增大 sort_buffer_size参数的设置(单路排序的内存大小)

② 增大 max_length_for_sort_data参数的设置(单次排序字段大小)

③ 去掉select 后面不需要的字段

分组优化

同 排序优化

实质是先排序后分组,遵循索引最左前缀

当无法使用索引列,增大max_length_for_sort_data参数的设置+增大sort_buffer_size参数的设置

WHERE 效率高于 HAVING

子查询优化

有索引:inner join 是最好的,其次是 in,exists 最糟糕

无索引:反之(待验证)

分页优化

优化前:EXPLAIN SELECT SQL_NO_CACHE * FROM emp ORDER BY deptno LIMIT 10000,40;会出现 using filesort

c5cf360b08ca7604ade4e134b79bf1dd.png

加索引后没效果:

b8dcad3ba9ca98040c7ba0eb187e4c3d.png

优化后:EXPLAIN SELECT SQL_NO_CACHE * FROM emp INNER JOIN (SELECT id FROM emp e ORDER BY deptno LIMIT 10000,40) a ON a.id=emp.id

7e5b85e151d9b521f3616f1fe6a7eeb9.png

优化思路: 先利用覆盖索引把要取的数据行的主键取到,然后再用这个主键列与数据表做关联(查询的数据量小了后再进行查询)。

去重查询

尽量不要使用 distinct 关键字去重,可以使用 group by+需要去重的字段,这个时候会用到索引

对于 IN 和 EXISTS 的使用

直接说个结论吧:EXISTS 后接大表,IN 后接小表,两表大小无差别两者都行

关联阅读

MySQL Explain 使用,看这一篇就够了

MySQL 查询语句执行过程

数据库优化指南

MySQL 索引入门

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值