【MySQL】orderby/groupby出现Using filesort根因分析及优化

在日常的数据库运维中,我们可能会遇到一些看似难以理解的现象。比如两个SQL查询语句,仅仅在ORDER BY子句上略有不同,却造成了性能的天壤之别——一个飞速完成,一个则让数据库崩溃。今天就让我们围绕这个问题,深入剖析MySQL的查询优化机制。

Q1 - 能否自我介绍下?

嗨,大家好,我是 小 明 (小明java问道之路)互联网大厂后端研发专家,2022博客之星TOP3/博客专家/CSDN后端内容合伙人、InfoQ(极客时间)签约作者、阿里云签约博主、全网5万粉丝博主。

一个8年开发经验的老兵,专注于面试/后端/源码/架构/算法,擅长面试高安全/可用/并发/性能的架构设计与演进、系统优化与稳定性建设。 

Q2 - 出现 Using filesort 问题分析?

  • 我们拿到两条SQL语句,第一条查询语句是:"WHERE time >= '2023-12-21 00:00:00' ORDER BY time ASC
  • 第二条查询语句是:"WHERE time >= '2023-12-21 00:00:00' ORDER BY id ASC“。

通过EXPLAIN命令对两条SQL进行分析后发现,在使用id作为排序字段时,MySQL使用了Using filesort 操作;但是在使用time作为排序字段时,却没有 Using filesort。而我们知道,Using filesort通常代表着磁盘排序,相较于内存排序,它的性能开销要大很多。

那么问题来了,既然id是主键,应该有更好的性能,为什么会导致 Using filesort 的出现呢?

Q3 - 问题原因是什么?

在我们的例子中,假设time字段的值是递增的,并且与id的增长趋势大致一致。那么在执行类似"WHERE time >='2023-12-21 00:00:00' ORDER BY time ASC"的查询时,MySQL可以通过time索引找到满足条件的第一个记录,然后顺序扫描后面的记录直到没有满足WHERE条件的记录为止。

在这个过程中,由于已经按照time字段的顺序读取记录,所以不需要额外的排序操作

但当我们改为"WHERE time >='2023-12-21 00:00:00' ORDER BY id ASC"时,就不能保证按id的顺序读取记录了。

因为虽然两个字段都是递增的,但并不能确保每个time值对应的id也是按顺序排列的。此时,MySQL查询优化器可能会选择扫描所有满足条件的记录,并把它们加载进入一个临时表进行排序,这样就产生了 Using filesort

Q4 - MySQL索引与查询优化器?

MySQL的索引可以提高查询速度,因为它们使得MySQL可以找到记录而无需扫描整个表。然而,索引并非万能的,它也会带来存储和管理的开销。所以,当MySQL选择执行计划时,会基于众多因素来考虑是否使用索引、使用哪种索引,以及如何使用索引。

NULL值和数据分布及唯一性都可以影响MySQL索引的使用效果。除此之外,MySQL的查询优化器还会根据查询条件和排序规则,选择最佳的索引进行操作。这就可能出现我们现在这个情况,即使id是主键,但如果在使用id进行排序时,不能有效利用索引,也可能产生 Using filesort 操作。

 

Q5 - 解决方案是什么?

  • 如果我们经常需要按照time和id排序的查询,一种解决方案是创建联合索引(time, id)。这样即使按照id排序,也能利用索引进行优化。因为对于联合索引来说,MySQL可以在满足time过滤条件的情况下,直接使用索引进行id的排序。
  • 可以尝试调整MySQL的sort_buffer_size参数。如果排序的数据量小于这个参数,那么MySQL可能会选择内存排序而非 Using filesort。需要注意的是,这个参数是每个连接独享的,设置得过大可能会浪费内存资源。

总结

理解MySQL索引的使用规则和查询优化器的工作原理,可以帮助我们更好地优化数据库性能,解决实际问题。同时,要明白没有最好的索引,只有最合适的索引。我们需要根据业务需求和实际数据分布,来选择和优化索引。

在本次的问题中,我们通过理解索引、排序以及查询优化器的工作原理,找出了导致问题的根源,并提出了相应的解决方案。

充分体现了,深入理解和掌握相关知识,对于我们解决实际问题的重要性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/286218.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

我这个小白坚持写作一整年,赚了多少?

今天是 2023 年的最后一天,和大家一起来一个年终复盘,主题就是:2023年,我到底赚了多少? 今年除了工作之外,我的重点都放在了写文章上。 截止到今天,已经在公众号上发布了 100 篇原创文章&…

selenium3自动化测试(这一篇就够了)——自学篇

📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…

瑞吉外卖项目详细总结

文章目录 瑞吉外卖1.技术栈2.项目文件架构3.业务功能模块(例子)3.1管理员登录接口层(Controller)3.2管理员登录实现层(ServiceImpl)3.3管理员登录服务层(Service)3.4管理员登录Mapper层 4.公共模块4.1 BaseContext(保存…

Cuk、Zeta和Sepic开关电源拓扑结构

Cuk、Zeta和Sepic变换器,三种拓扑结构大致类似。不同点在于电感和二极管,MOS管的位置关系的变化。 Cuk电源是一种非隔离的直流电源转换器,其基本结构包括输入滤波电容、开关管、输入电感、输出电感和输出电容等元件。Cuk电路可以看作是Boost和Buck电路的…

day5--java基础编程:异常,内部类

6 异常 6.1 异常概述 出现背景: 在使用计算机语言进行项目开发的过程中,即使程序员把代码写得尽善尽美,在系统的运行过程中仍然会遇到一些问题,因为很多问题不是靠代码能够避免的,比如:客户输入数据的格式&#xff0c…

磁盘管理与文件系统

步骤: 1.建立分区(必须分区) 在文件中的格式开头为b ,块设备 2.文件系统 因公安是个硬件设备,是一类软件的总称,管理文件的功能,下载文件占硬盘的空间 3.挂载 将硬盘与系统内的文件夹做关…

图论及其应用(匈牙利算法)---期末胡乱复习版

目录 题目知识点解题步骤小结题目 T1:从下图中给定的 M = {x1y4,x2y2,x3y1,x4y5},用 Hungariam算法【匈牙利算法】 求出图中的完美匹配,并写出步骤。 知识点 关于匈牙利算法: 需要注意的是,匈牙利算法仅适用于二分图,并且能够找到完美匹配。什么是交替路?从一个未匹…

Linux/Unix/国产化操作系统常用命令(二)

目录 后CentOS时代国产化操作系统国产化操作系统有哪些常用Linux命令关于Linux的LOGO 后CentOS时代 在CentOS 8发布后,就有了一些变化和趋势,可以说是进入了"后CentOS时代"。这个时代主要表现在以下几个方面: CentOS Stream的引入…

刚来实习就跑路,可行么?

最近 编程导航 的一位鱼友问了个让我血压升高的问题: 鱼友提问 鱼皮你好,我投了两周简历,然后昨天面了一个小厂的远程实习并且拿到了 offer,我要不要试试呢? 我在顾虑比如我如果在远程实习期间找到一个中厂或者大厂…

vite项目中动态引入src失败的问题解决:require is not defined

问题复现 静态引入路径(无问题) <el-menu-item v-for"(item,index) in menuList" :index"item.name" :key"index"><img class"menuItemImg" src"../svg/router/homePage.svg" alt"">{{ item.meta.c…

浙大链协2023年终总结

2 0 2 4 元旦 快乐 龙腾虎跃 01 引言 俗话说&#xff1a;"币圈一天&#xff0c;人间十年"&#xff0c;数字货币一天的涨跌可能抵上其他资产价格一年的波动幅度。而经历过漫长的熊市后&#xff0c;铭文的火爆十分生动地表述了这一口号...... 2023年&#xff0c;浙大链…

odoo17后台启动过程3——三种server

文件位置&#xff1a;odoo\service\server.py 1、三种server&#xff1a; 1.1、Threaded 这是Odoo默认的选项&#xff0c;线程模式&#xff0c;我们知道python的多线程并不是真正的多线程&#xff0c;所以&#xff0c;这种模式下&#xff0c;并发性能较低&#xff0c;也无法利…

使用拉普拉斯算子的图像锐化的python代码实现——数字图像处理

原理 拉普拉斯算子是一个二阶导数算子&#xff0c;用于图像处理中的边缘检测。它通过计算图像亮度的二阶空间导数来工作&#xff0c;能够突出显示图像中的快速变化区域&#xff0c;如边缘。 图像锐化的原理&#xff1a; 图像锐化是指增强图像中的边缘和细节&#xff0c;使图像…

Python基础知识:整理1 使用函数实现银行ATM操作

定义一个全局变量&#xff1a; money, 用来记录银行卡余额&#xff08;默认为5000000&#xff09; 定义一个全局变量&#xff1a; name, 用来记录客户姓名&#xff08;启动程序时输入&#xff09; 定义如下函数&#xff1a; 查询余额的函数&#xff1b; 存款函数&#xff1b; 取…

blender mix节点和它的混合模式

Mix 节点是一种用于混合两个颜色或者两个图像的节点&#xff0c;它有以下几个输入和输出&#xff1a; Color1&#xff1a;用于接收第一个颜色或者图像&#xff0c;也就是基色。Color2&#xff1a;用于接收第二个颜色或者图像&#xff0c;也就是混合色。Fac&#xff1a;用于控制…

第六节、项目支付功能实战-保证金支付、支付回调

摘要 上一节中,我们申请了商户的证书、APIv3密钥,以及编写了微信平台证书的下载的相关代码,并以微信平台证书下载和微信下单接口为例分析了sdkapi的使用、sdk是如何封装加签和验签的流程的。这一节我们将结合实际保证金支付业务来实现整个支付的功能。 功能实现 1、实现小…

RDS快速入门

目录 实例创建 设置白名单 RDS&#xff08;Relational Database Service&#xff09;是一种托管式的关系型数据库服务&#xff0c;它为用户提供了一种简单、可靠、安全的方式来部署、操作和扩展数据库。具有安全可靠、解决运维烦恼、有效降低成本和自研增加等四大特性&#x…

chromium通信系统-ipcz系统(九)-ipcz系统代码实现-跨Node通信-代理和代理消除

chromium通信系统-ipcz系统(六)-ipcz系统代码实现-跨Node通信-基础通信 一文我们分析了跨Node的基础通信过程。 a进程和b进程通信的过程。 但在程序中a进程将自己打开的一对portal中的一个portal传递给了b进程。由于篇幅问题这个过程我们并没有分析&#xff0c;这篇文章我们就来…

学习MySQL(5.7)第二战:四大引擎、账号管理以及建库(干货满满)

目录 前言&#xff1a; 一.数据库存储引擎 1.存储引擎简介 存储引擎查看 support字段说明 2.四大引擎详细介绍 InnoDB MylSAM MEMORY Archive 二.数据库管理 1.元数据库简介 2.元数据库分类 infomation_schema mysql performance_schema ​编辑3.数据库…

协议基础笔记

Android串口使用方法_android-serialport的使用-CSDN博客 安卓与串口通信-基础篇_安卓串口通信-CSDN博客 串口简介 串口通信是Android智能硬件开发所必须具备的能力&#xff0c;市面上类型众多的外设基本都是通过串口进行数据传输的&#xff0c;所以说不会串口通信根本就做不…