首页 > 数据库 >Mysql多表连接order by优化场景

Mysql多表连接order by优化场景

时间:2024-05-10 15:35:13浏览次数:38  
标签:多表 Mysql oId order SQL msg Using filesort id

一天,DBA突然发来一条慢SQL告警, SQL如下:

SELECT
  s.msg,
  t.msg,
  o.msg,
  GROUP_CONCAT(t.tId) AS tIdList
FROM
  t_o o
  LEFT JOIN t_s s ON o.id= s.oId
  LEFT JOIN t_t t ON t.oId= o.id
WHERE
  o.type = 'B'
  AND o.status = 'HAS_PAY'
  AND t.type = '2002'
  AND o.time <= '2023-11-11 15:46:41.0'
  AND o.time>= '2023-11-04 15:46:41.0'
GROUP BY
  o.id
ORDER BY
  o.id DESC

经验老练的导师(瞧了瞧我这条SQL):你把order by o.id 换成 t.oId 或者 s.oId试试看

我:啊,这有什么不一样的吗?

经验老练的导师(不屑的表情):你试试就晓得了咯

我把SQL调整如下:

SELECT
  s.msg,
  t.msg,
  o.msg,
  GROUP_CONCAT(t.tId) AS tIdList
FROM
  t_o o
  LEFT JOIN t_s s ON o.id= s.oId
  LEFT JOIN t_t t ON t.oId= o.id
WHERE
  o.type = 'B'
  AND o.status = 'HAS_PAY'
  AND t.type = '2002'
  AND o.time <= '2023-11-11 15:46:41.0'
  AND o.time>= '2023-11-04 15:46:41.0'
GROUP BY
  t.oId
ORDER BY
  t.oId DESC

一运行发现SQL的查询时间变成了100ms(原SQL是300多ms)

我:蛙趣,什么情况,佬,这是玄学嘛?

经验老练的导师(得意洋洋):因为你原SQL应该用连表后的临时表进行了排序,没有走索引,所以效率慢,你Explain一下就知道了

explain结果

  • 优化前的SQL:Using index condition; Using temporary; Using filesort
  • 优化后的SQL:Using where

首先讨论一下Using filesort,我们知道Mysql是有两种排序的,index 和 filesort,如果order by的条件不在索引列上就会filesort
但是我们的o.id是主键呀,有索引的哦。

Using temporary,表示用到了临时表,Mysql连表的时候会分驱动表和非驱动表,驱动表默认是数据最小的表,另外的叫非驱动表
首先处理驱动表的数据,之后再和非驱动表进行连接匹配操作。因此对于驱动表的字段是可以直接排序的,而非驱动表的字段需要合并结果(临时表)进行排序,于是产生了filesort

到这里就可以解释上述现象了,并且上述SQL还可以用straight_join来解决,这里不赘述。

标签:多表,Mysql,oId,order,SQL,msg,Using,filesort,id
From: https://www.cnblogs.com/lhbilibili/p/18184046

相关文章

  • Python-有序字典OrderedDict练习题
    问题:读取键盘输入结果,创建n个键值对,将其排序后放入有序字典并输出。详细描述:根据提示,实现函数功能:读取n(n>0)行输入,以每一行的数据为key,行号(从0开始)为value,建立n对键值对,然后将他们按照key排序后,放入一个有序字典,最后输出这个有序字典。importcollectionsdefFunc():pairs......
  • Mysql 查询后进行插入
    Mysql查询后进行插入,具体要求如下:1、有2张表,sys_role_user和sys_role_user_123,两张表结构相同,表字段有role_id、user_id2、role_id和user_id是唯一索引3、把sys_role_user中没有的数据从sys_role_user_123中复制到sys_role_user表中 INSERTINTOsys_role_user(role_i......
  • dokcer-compose.yml 方式运行 mysql 8.0
    先不映射指定配置目录,./conf/mysql,docker容器开起来后,复制容器内/etc/mysql到宿主机,然后添加目录映射:-"./conf/mysql:/etc/mysql",这样就可以将配置里保存在宿主机了。version:'3.0'networks:mysql_network:name:mysql_networkexternal:trueservices:......
  • php使用mysql-text字段存取json字符串
    PHP保存时过滤掉双引号&单引号&tabfunctionformartJsonString($jsonString=''){ $jsonString=str_replace("'","",$jsonString); $jsonString=str_replace('\"',"",$jsonString); $jsonString=st......
  • selenium+mysql 爬取LEI官网数据
    importtimefromseleniumimportwebdriverfromselenium.webdriver.chrome.serviceimportServicefromselenium.webdriver.common.byimportByfromselenium.webdriver.support.uiimportWebDriverWaitfromselenium.webdriver.supportimportexpected_conditions......
  • css border-radius 如何设置不占div宽度,向外突出
    在CSS中,border-radius用于创建元素的圆角边框,但边框圆角本身是包含在元素的总宽度和高度内的,并不会额外占用外部空间或使元素尺寸变大。如果你想让圆角“向外突出”,即不占用div本身的宽度和高度,可以通过一些技巧来模拟这种效果。一种常见的方法是使用伪元素(::before和::afte......
  • mysql主从同步
    6.MySQL主从同步、主从同步模式6.MySQL主从同步、主从同步模式主从同步原理(1)Master,记录数据更改操作①启用binlog日志②启用binlog日志格式③设置server_id(2)Slave运行2个线程①Slave_IO:复制master主机binlog日志文件里的SQL到本机的relay-log文件里②Slave-SQL......
  • 配置mysql多实例
    配置mysql多实例需要专用的、支持多实例的mysql软件。这里用到的是mysql-5.7.24-linux-glibc2.12-x86_64.tar.gz解压mysql软件包tar-xfmysql-5.7.34-linux-glibc2.12-x86_64.tar.gz-C/usr/local/mysql配置多实例vim/etc/my.cnf[mysqld_multi]            ......
  • mysql导入导出整个数据库
    要将整个MySQL数据库导入到另一个MySQL实例中,您可以使用mysqldump工具导出数据库,并使用mysql客户端导入它。以下是一般的步骤:1. 导出数据库使用mysqldump工具导出数据库到一个SQL文件。例如,如果您要导出名为mydatabase的数据库,可以这样做:mysqldump-u[username]-pmydatabas......
  • mysql事务
    1.事务  事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。2.控制事务控制事务一查看/设置事务提交方式SELECT@@autocommit;SET@@autocommit=0;提交事......