MySQL慢SQL优化方案汇总

这篇具有很好参考价值的文章主要介绍了MySQL慢SQL优化方案汇总。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 MySQL慢SQL优化方案汇总,mysql经验总结,mysql,sql,数据库

⛰️个人主页:     蒾酒

🔥系列专栏《mysql经验总结》

🌊山高路远,行路漫漫,终有归途


目录

写在前面

优化思路

避免查询不必要的列

分页优化

索引优化

JOIN优化

排序优化

UNION 优化

写在最后


写在前面

本文介绍了MySQL常见的优化慢sql的手段,坚持看完相信对你有帮助。

同时欢迎订阅MySQL系列专栏,持续分享MySQL的使用经验。

优化思路

慢sql的优化无非是从两个方向着手

  • SQL语句本身的优化
  • 据库设计的优化

下面进行渐进式的分享一些常见优化手段

避免查询不必要的列

查询应该精准的查出需要的列,对于select * 的写法要避免,因为所有字段查出来不仅sql查询执行慢,若是直接返回给前端,大量的数据也会影响网络传输效率。

分页优化

对于数据量特别大,这时分页会比较深,查询扫描的数据量会比较大效率自然低,我们就需要进行分页优化

假设我们有一个包含大量订单记录的订单表,其中每个订单都有一个唯一的不包含业务逻辑的主键,并且我们想要查询最近一个月的订单并按照订单id从小到大进行分页显示某页。

假设出现深分页的sql如下:

select * from orders where order_date >= date_sub(now(), interval 1 month)
 order by id limit 100000, 10;

执行此SQL时需要先扫描到100000行,然后再去取10行,但是随着扫描的记录数越多,SQL的性能就会越差,因为扫描的记录越多,MySQL需要扫描越多的数据来定位到具体的多少行,这样耗费大量的 IO 成本和时间成本。

对于解决该深分页问题通常有两种方法

1.延迟关联

先通过 where 条件提取出主键,在将该表与原数据表关联,通过主键 id 提取数据行,而不是通过原来的二级索引提取数据行

优化后sql:

select o.*
from (
    select id
    from orders
    where order_date >= date_sub(now(), interval 1 month)
    order by id
    limit 100000, 10
) as sub
join orders as o on sub.id = o.id;

优化后SQL中的子查询只取主键id,可避免通过二级索引中的主键去回表查询,这样性能会快一些。

2.id偏移量

偏移量就是找到 limit 第一个参数对应的主键值,根据这个主键值再去过滤并 limit,这种方法又称为基于游标的分页。基于游标的分页的前提是需要保证主键或排序列的连续性、唯一性。

优化后sql:

select *
from orders
where id >= (select id from orders order by id limit 100000, 1)
order by id
limit 10;

这种方法相对于原来直接使用偏移量和限制结果数量的方式,可以在大数据集上提供更稳定和一致的性能,因为它不需要扫描和跳过大量的行。

索引优化

通过合理的设计和使用索引,能够有效优化sql性能,这也是我们使用最多的手段。

下面介绍一下如何进行索引优化:

使用覆盖索引

InnoDB使用二级索引查询数据时会回表,但是如果索引的叶节点中已经包含要查询的字段,那它没有必要再回表查询了,这就叫覆盖索引,还有一个简单的理解查询列都是索引列。

示例:

select product_name, price
from products
where category_id = 1;
create index idx_category_id on products (category_id, product_name, price);

避免使用or查询

在 MySQL 5.0 之前的版本要尽量避免使用 or 查询,可以使用 union 或者子查询来替代,因为早期的MySQL版本使用 or 查询可能会导致索引失效,高版本引入了索引合并,解决了这个问题,不过建议大家在实际使用中还是规范写法,能不用就少用。

避免使用 != 或者 <>操作符

SQL中,不等于操作符会导致查询引擎放弃查询索引,引起全表扫描,即使比较的字段上有索引。解决方法:通过把不等于操作符改成 or,可以使用索引,避免全表扫描

id <>'aaa'
id >'aaa'or id<'aaa

适当使用前缀索引

适当地使用前缀索引,可以降低索引的空间占用,提高索引的查询效率。比如,邮箱的后缀都是固定的“@xxx.com”,那么类似这种后面几位为固定值的字段就非常适合定义为前缀索引

create index idx_email_prefix on users (email(6)); -- 假设后缀长度为6

需要注意的是,前缀索引也存在缺点,MySQL无法利用前缀索引做 order by和 group by 操作,也无法作为覆盖索引。

避免列上函数运算

要避免在列字段上进行算术运算或其他表达式运算,否则可能会导致存储引擎无法正确使用索引,从而影响了查询的效率。

select order_id
from orders
where total_amount / 2 > 100

正确使用联合索引

使用联合索引的时候,注意最左匹配原则。 

JOIN优化

优化子查询

尽量使用 Join 语句来替代子査询,因为子査询是嵌套查询,而嵌套查询会新创建一张临时表,而临时表的创建与销毁会占用一定的系统资源以及花费一定的时间,同时对于返回结果集比较大的子查询,其对查询性能的影响更大 

小表驱动大表

关联查询的时候要拿小表去驱动大表,因为关联的时候,MySQL内部会遍历驱动表,再去连接被驱动表

select name from小表 left join 大表;

适当增加冗余字段

增加冗余字段可以减少大量的连表查询,因为多张表的连表查询性能很低,所有可以适当的增加冗余字段,以减少多张表的关联查询,这是以空间换时间的优化策略。

避免使用 JOIN 关联太多的表

《阿里巴巴 Java 开发手册》规定不要 join 超过三张表,第一join 太多降低査询的速度,第二 join 的buffer 会占用更多的内存。

排序优化

利用索引扫描做排序

MYSQL有两种方式生成有序结果:一是对结果集进行排序的操作,二是按照索引顺序扫描得出的结果,索引是排好序的数据结构,自然是有序的。
但是如果索引不能覆盖查询所需列(覆盖索引),就会每扫描一条记录回表查询一次(逐个获取),这个读操作是随机 IO,通常会比顺序全表扫描还慢,有时会直接放弃使用索引转为全表扫描。因此,在设计索引时,尽可能使用同一个索引既满足排序又用于查找行。

#索引为 a,b,c
select b,c from test where a like 'aa%' order by b,c;

只有当索引的列顺序和 ORDER BY 子句的顺序完全一致,并且所有列的排序方向都一样时,才能够使用索引来对结果做排序。

UNION 优化

条件下推

MySQL处理 union 的策略是先创建临时表,然后将各个查询结果填充到临时表中最后再来做查询,很多优化策略在 union 查询中都会失效,因为它无法利用索引。所以需要将 where、limit 等子句下推到 union 的各个子查询中,以便优化器可以充分利用这些条件进行优化。

此外,除非确实需要服务器去重,一定要使用 union all,如果不加 all 关键字,MySQL 会给临时表加上distinct 选项,这会导致对整个临时表做唯一性检查,代价很高。

写在最后

MySQL优化慢SQL的6种方式到这里就结束了,本文介绍了常见慢sql优化的有效方式。任何问题评论区或私信讨论,欢迎指正。文章来源地址https://www.toymoban.com/news/detail-854857.html

到了这里,关于MySQL慢SQL优化方案汇总的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mysql数据库结构优化汇总

         设计表以最大限度地减少其在磁盘上的空间。这可以减少写入磁盘和从磁盘读取的数据量,从而带来巨大的改进。较小的表通常需要较少的主内存,而它们的内容在查询执行过程中被主动处理。表数据的任何空间减少也会导致更小的索引可以更快地处理。 尽可能使用最

    2024年02月07日
    浏览(33)
  • [MySQL]SQL优化之sql语句优化

    🌈键盘敲烂,年薪30万🌈 目录 一、索引优化 回顾: 📕索引分类: 📕索引失效: 📕设计原则: 📕SQL性能分析 二、SQL优化 语句优化 📕 insert语句: 📕 主键优化: 📕 order by优化: 📕 group by优化: 📕 limit 优化 📕 count 优化 📕 update 优化  📕索引分类: 一般分类:主

    2024年02月04日
    浏览(32)
  • MySQL查询优化方案汇总(索引相关)

    类型隐式转换 大坑 大数据深度分页,用主键 避免使用MySQL函数 避免类型的隐式转换 避免使用函数或表达式,尽量只让数据库做纯粹的增删改查。 避免使用不等值做排除法 避免使用null值 减少大字段查询,避免使用*,不说磁盘io的损耗,连网络带宽都跟着损耗。 如果只sel

    2024年03月09日
    浏览(35)
  • 【MySQL】SQL优化(九)

    🚗MySQL学习·第九站~ 🚩本文已收录至专栏:MySQL通关路 ❤️文末附全文思维导图,感谢各位点赞收藏支持~ ⭐学习汇总贴,超详细思维导图:【MySQL】学习汇总(完整思维导图) 如果我们需要一次性往数据库表中插入多条记录: 我们可以从以下三个方面进行优化~ (1.1) 批量插入数

    2024年02月15日
    浏览(36)
  • [MySQL--SQL优化]

    如果一次性需要 插入大批量数据 ,使用 insert语句插入性能较低 ,此时 可以使用MySQL数据库提供的load指令 进行插入。 操作如下: 针对于大数据量的情况下 分页查询时越往后就会变得越耗时。所以我们需要通过优化limit来提升效率 优化思路:自己计数。 比如:我们可以自己

    2024年02月07日
    浏览(81)
  • 【MySQL】sql如何优化?

    (1)通过SQL监控、请求、日志等找出耗时的SQL语句; (2)使用Explain方式查看SQL耗时的具体原因; (3)根据实际情况解决:索引、缓存、左右连接 select_type:简单查询or复杂查询?simple、primary、subquery、deriveer、union。 type:SQL关联类型, system const eq_ref ref range index All 。一般

    2024年02月07日
    浏览(36)
  • 【MySQL】SQL优化

    记录Mysql学习笔记,大部分图片来自黑马程序员MySQL教程。 插入多条数据的时候,可以按以下方式优化。 批量插入时,一次性插入的数据建议不超过1000条。 MySQL默认自动提交事务,所以插入操作会频繁地开启和提交事务,建议手动提交。 主键顺序插入性能高于乱序插入。

    2024年02月03日
    浏览(27)
  • MySQL篇之SQL优化

    表的设计优化(参考阿里开发手册《嵩山版》) :         1. 比如设置合适的数值(tinyint   int   bigint),要根据实际情况选择。         2. 比如设置合适的字符串类型(char和varchar)char定长效率高,varchar可变长度,效率稍低。         1. SELECT语句务必指明字段

    2024年02月19日
    浏览(32)
  • MySQL查询性能优化——SQL优化(四)

      目录 1、批量插入数据 1.1 linux环境下 1.1.1 开启文件读取 1.1.2 load数据 1.2 windows环境下 2、order by优化 2.1 最左前缀 3、group by 3.1 最左前缀 4、count优化 5、or条件优化   在上一期说到索引的使用,这期来聊一下SQL优化,也是平常写SQL的时候常用到的。 在前几期也有聊到过批量插

    2024年02月19日
    浏览(41)
  • 【MySQL数据库】MySQL 高级SQL 语句一

    ) % :百分号表示零个、一个或多个字符 _ :下划线表示单个字符 ‘A_Z’:所有以 ‘A’ 起头,另一个任何值的字符,且以 ‘Z’ 为结尾的字符串。例如,‘ABZ’ 和 ‘A2Z’ 都符合这一个模式,而 ‘AKKZ’ 并不符合 (因为在 A 和 Z 之间有两个字符,而不是一个字符)。 ‘ABC%’

    2024年02月09日
    浏览(66)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包