不要用 in + 子查询

news2024/11/16 21:31:40

前两天我的 VIP 用户向我抛出了一个 SQL 问题,他的 MySQL 是 8.x版本:

大概意思如下 sql :

select * from A where id in (
  select max(id) as id from A 
   where task_id in(1,2,3) 
    group by task_id
);

这个 A 表中是有 task_id 这个索引的。

一眼看去这个查询没啥问题,子查询里会利用 task_id 这个索引,然后外面的这个查询会上 id 这个主键索引。

而事实是:

一看 explain ,果然走了全表扫描:

可以看到子查询用上了 taskId 这个索引,而外部的查询走的是全表扫描,大概扫描了 890W 的数据,所以查询花了 1 分 30 秒。

那么问题来了:明明有主键索引不用,mysql 为什么要选择全表?

我也不知道。

MySQL 有个优化器,它会决定最终以怎么样的形式、选择那个索引来生成最终的执行计划。

对将要执行的 SQL 而言,优化器会有成本模型,它会根据当前表的一些估算值结合当前的 SQL 语句进行打分,比如如果用了索引 A 需要多少 I/O 成本、CPU 成本,如果用索引 B 要多少I/O、CPU成本。

总而言之,它有自己的一套规则,会根据估计值预算成本,根据成本最终生成执行计划。

篇幅有限具体不多介绍,有兴趣的话看下官网:https://dev.mysql.com/doc/refman/8.0/en/cost-model.html

既然是预算,那就有可能不准,所以有时候就会产生该走索引却全表扫描的情况(因为算出的成本走全表扫描反而更低)。

所以针对上面这种情况,我让他加了强制用主键的操作 force index(PRIMARY),但是并没有生效,还是走了全表。

可以看到扫描了大约 996w 行数据(表数据有新增,所以从800w多变成了900多w)。

我自己估计:大致就是因为子查询的结果不确定,MySQL 不知道 in 的值到底有多大,所以保守型的选择了全表(我猜的,具体的逻辑估计得看源码,不过最终表现的事实确实如此)。

问题就在 in 的值大小不确定。

通过子查询,我们自己其实也无法保证 in 的值到底是多少。

所以最后的方案是抛弃 in 的方式,采用 inner join 的方式来改造 sql  实现。

改造 SQL 如下:

select * from A a inner join (
  select max(id) as id from A 
   where task_id in(1,2,3) group by task_id
) b 
on a.id = b.id;

这样改造以后,进行了一波 explain,结果如下:

查询结果秒出,可以看下第二行,用上了主键索引,全部扫描的行数加起来也就 600 多。

所以我们换了一种方式来使得 MySQL 正常的用上索引且所要的结果是一致的。

这里也建议,如果 sql 是包含子查询的 in 查询,那么最好换成 join 的方式,因为我们不能保证 in 的查询一定会用上索引,万一来个全表扫描,在表数据量比较大的场景,很容易产生阻塞,多来几个这样的阻塞,数据库连接不可用,服务可能就挂了。

在测试环境看起来没问题,一到生产就 GG。

所以能不用 in + 子查询,就不要用,可以用 join 来替代实现。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【转换】编码转换工具笔记

应用场景 应用场景是程序整合第三方库多平台运行,第三方库window平台编译,代码移植到linux出现bom问题 思考解决 windows使用utf-8编码,linux使用utf-8无bom编码 工具主要针对utf-8编码文件,能够批量添加删除BOM,无…

SpringBoot获取项目日志

目的 对于布署在远端的服务,我们想快速的获取到日志。对于使用了日志服务,也可能因为上报间隔太长,日志不够实时。 所以想通过一些方式,可以不用进入到容器内也可以简单快速获取到日志,而且是实时的日志。目标就是获…

c语言进阶-动态内存管理

重点学习内容 动态内存管理四大函数 Malloc 内存申请函数 返回值是无类型的指针,指向分配的内存的首地址。申请失败会返回空指针。 malloc返回值是void*类型,使用时需要强制转换成所需类型。 malloc和free匹配使用,但是如果不free释放内存&…

解析3D视觉系统在引导金属件上下料中的应用

原创 | 文 BFT机器人 引言 Introduction 机器视觉技术作为一种高科技的智能化技术,正在工业生产领域发挥着越来越重要的作用。它利用计算机视觉技术,通过获取、处理和分析图像,实现对产品和工艺过程的监测、检测和控制。 随着人工智能技术的…

[SUCTF2019]hardcpp

前言 又遇到ollvm了 解混淆 可以直接用angr运行脚本去除除控制流平坦化,最好在ancoda等管理环境里面安装angr不然问题很多 https://github.com/Pure-T/deflat 去除前 去除后,它将多余的直接nop了 分析 主要加密区域位于匿名函数这一块&#xff0c…

前端学习——Web API(Day1)

Web API基本认知 Web API 基本认知 作用和分类 DOM DOM树 DOM对象 获取DOM对象 根据CSS选择器来获取DOM元素 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" …

【教学类-36-08】转学“纪念册“留念(生肖用midjounery-niji)

作品样式 背景需求&#xff1a; 即将离开班级&#xff0c;我想收集一份28个孩子的绘画册做——留念转学纪念册. 材料准备&#xff1a; 幼儿照片 ——3月初到中6班拍摄的幼儿手持学号名字纸的照片&#xff08;为了背诵幼儿信息而拍摄的照片&#xff0c;统一竖版&#xff09; 生…

jmeter 连接数据库常见报错

1. 不允许主机连接到MySQL 报错信息&#xff1a; Response message:java.sql.SQLException: Cannot create PoolableConnectionFactory (null, message from server: "Host 192.168.1.6 is not allowed to connect to this MySQL server") 说明&#xff1a;本机的地…

代码随想录day10

232. 用栈实现队列 思路&#xff1a;用两个list去模拟栈的操作&#xff0c;一个入栈list&#xff0c;一个出栈list. 并且了解栈的操作&#xff0c;pop,peek,push. 代码&#xff1a; def __init__(self):self.stack1 [] #入栈self.stack2[] #出栈def push(self, x: int) ->…

【Linux】常用网络命令:ping\netstat\mount\ifconfig

ping命令用于检测主机&#xff0c;执行ping命令指令会使用ICMP传输协议&#xff0c;发出请求回应的信息&#xff0c;若远程主机的网络功能没有问题&#xff0c;就会回应该信息。   netstat命令用于显示网络状态&#xff0c;利用netstat 指令可让你得知linux系统的网络情况。…

图像 跟踪 - MOTR: End-to-End Multiple-Object Tracking with Transformer (ECCV 2022)

MOTR: End-to-End Multiple-Object Tracking with Transformer - 使用Transformer进行端到端多目标跟踪&#xff08;ECCV 2022&#xff09; 摘要1. 引言2. 相关工作3. 方法3.1 目标检测中的查询3.2 检测查询和跟踪查询3.3 Tracklet-Aware标签分配3.4 MOTR架构3.5 查询交互模块3…

git-创建文件夹方式管理分支

文章目录 前言一、效果图二、git命令总结 前言 下面介绍一个git创建文件夹的方式管理分支的方法&#xff0c;在sourcetree上显示目录样式&#xff0c;好对每个版本做管理&#xff0c;可以更方便追踪历史版本代码。 一、效果图 1、git文件夹方式管理分支 二、git命令 1、在本…

SSMP整合案例(14) 将界面查询改为分页查询

前面几篇文章过后 我们的项目基本环境就算搭好了 但是 我们下面的分页显然就是个摆设 这里 我们就先将查询的方法改成分页的 我们 java项目之前做了这个分页的函数 那么 我们vue项目 直接在 src下的 api 下的bookApi.js中加上对应的函数 export function getPage(params){r…

动态SLAM论文(8) — DynaSLAM II: Tightly-Coupled Multi-Object Tracking and SLAM

目录 1 Introduction 2 Related Work 3 Method A. 符号表示 B. 物体数据关联 C. 以对象为中心的表示 D. 对象束调整 E. 边界框 4 Experiments A. 视觉里程计 B. 多目标跟踪 C. 时间分析 5 结论和未来工作 摘要 —— 在视觉SLAM算法中&#xff0c;假设场景是刚性的是…

快速入门uniapp——从环境搭建到项目实践

&#x1f642;博主&#xff1a;小猫娃来啦 &#x1f642;文章核心&#xff1a;快速入门uniapp——从环境搭建到项目实践 文章目录 初步介绍UniApp开发环境搭建下载和安装UniApp开发工具创建新项目&#xff08;HBuilderX&#xff09;开发工具界面介绍 UniApp基础知识页面结构页面…

Rdkit|SMARTS语言应用

github&#xff1a;地址 文章目录 Rdkit|SMARTS语言应用子结构搜索HasSubstructMatch(patt)得到子结构序列GetSubstructMatch删除子结构AllChem.DeleteSubstructs(m,patt)取代基替换AllChem.ReplaceSubstructs(m, patt, rep)显示核心结构显示侧链结构 Chem.ReplaceCore分子拆分…

vue transition标签用法

transition标签 是Vue的内置动画标签&#xff0c;在插入/更新/移除DOM元素时&#xff0c;在合适的时候给元素添加样式类名&#xff08;配合css样式使用&#xff0c;实现动画效果&#xff09; 注意&#xff1a; 1.transition标签只能包含一个元素&#xff1b;如果里面写了多个…

如何从零开始学习自动化测试?终于找到靠谱的教程了

目录 前言 测试基础 Python基础 selenium appium requests unittest 项目实战&#xff1a; 总结&#xff1a; 前言 最近有几个小伙伴在后台给安静私信说&#xff0c;如何学习自动化&#xff0c;不知道如何入手&#xff1f;在网上看的资料都是乱七八糟的&#xff0c;每…

接口返回慢 图片加载失败问题

该图片是通过后端接口返回picUrl来给img的src赋值 但是后端接口响应较慢 导致html加载完 data也没赋到值 图片加载裂开 解决办法&#xff1a;img标签添加error事件获取错误信息回调 <img v-if"certificateUrl" :src"certificateUrl" class"certif…

三星强势进军车用半导体,2025年开始提供8英寸氮化镓代工服务

根据来自韩国商业报导的消息&#xff0c;三星电子最近在美国和韩国两地举办了一个专门针对行业人士的论坛&#xff0c;旨在展示2023年的三星晶圆代工技术。在这次活动中&#xff0c;三星宣布将在2025年开始提供面向消费者、数据中心及汽车应用的8英寸氮化镓&#xff08;GaN&…