0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

MySQL到底是join性能好,还是in一下更快呢?

jf_ro2CN3Fa 来源:芋道源码 2023-10-31 15:40 次阅读


先总结:

  1. 数据量小的时候,用join更划算
  2. 数据量大的时候,join的成本更高,但相对来说join的速度会更快
  3. 数据量过大的时候,in的数据量过多,会有无法执行SQL的问题,待解决

事情是这样的,去年入职的新公司,之后在代码review的时候被提出说,不要写join,join耗性能还是慢来着,当时也是真的没有多想,那就写in好了,最近发现in的数据量过大的时候会导致sql慢,甚至sql太长,直接报错了。

这次来浅究一下,到底是in好还是join好,仅目前认知探寻,有不对之处欢迎指正

以下实验仅在本机电脑试验

一、表结构

1、用户表

2878693a-779a-11ee-939d-92fbcf53809c.jpg
CREATETABLE`user`(
`id`intNOTNULLAUTO_INCREMENT,
`name`varchar(64)CHARACTERSETutf8mb4COLLATEutf8mb4_general_ciNOTNULLCOMMENT'姓名',
`gender`smallintDEFAULTNULLCOMMENT'性别',
`mobile`varchar(11)CHARACTERSETutf8mb4COLLATEutf8mb4_general_ciNOTNULLCOMMENT'手机号',
`create_time`datetimeNOTNULLCOMMENT'创建时间',
PRIMARYKEY(`id`),
UNIQUEKEY`mobile`(`mobile`)USINGBTREE
)ENGINE=InnoDBAUTO_INCREMENT=1005DEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_general_ci

2、订单表

288a61f8-779a-11ee-939d-92fbcf53809c.jpg
CREATETABLE`order`(
`id`intunsignedNOTNULLAUTO_INCREMENT,
`price`decimal(18,2)NOTNULL,
`user_id`intNOTNULL,
`product_id`intNOTNULL,
`status`smallintNOTNULLDEFAULT'0'COMMENT'订单状态',
PRIMARYKEY(`id`),
KEY`user_id`(`user_id`),
KEY`product_id`(`product_id`)
)ENGINE=InnoDBAUTO_INCREMENT=202DEFAULTCHARSET=utf8mb4COLLATE=utf8mb4_general_ci

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 视频教程:https://doc.iocoder.cn/video/

二、先来试少量数据的情况

用户表插一千条随机生成的数据,订单表插一百条随机数据

查下所有的订单以及订单对应的用户

下面从三个维度来看

多表连接查询成本 = 一次驱动表成本 + 从驱动表查出的记录数 * 一次被驱动表的成本

1、join

JOIN:

explainformat=jsonselectorder.id,price,user.`name`from`order`joinuseronorder.user_id=user.id;

子查询:

selectorder.id,price,user.`name`from`order`,userwhereuser_id=user.id;
2894560e-779a-11ee-939d-92fbcf53809c.jpg

2、分开查

select`id`,price,user_idfrom`order`;
289b8532-779a-11ee-939d-92fbcf53809c.jpg
selectnamefromuserwhereidin(8,11,20,32,49,58,64,67,97,105,113,118,129,173,179,181,210,213,215,216,224,243,244,251,280,309,319,321,336,342,344,349,353,358,363,367,374,377,380,417,418,420,435,447,449,452,454,459,461,472,480,487,498,499,515,525,525,531,564,566,580,584,586,592,595,610,633,635,640,652,658,668,674,685,687,701,718,720,733,739,745,751,758,770,771,780,806,834,841,856,856,857,858,882,934,942,983,989,994,995);[in的是order查出来的所有用户id]
28a6c58c-779a-11ee-939d-92fbcf53809c.jpg

如此看来,分开查和join查的成本并没有相差许多

3、代码层面

主要用php原生写了脚本,用ab进行10个同时的请求,看下时间,进行比较

ab -n 100 -c 10

in

$mysqli=newmysqli('127.0.0.1','root','root','test');
if($mysqli->connect_error){
die('ConnectError('.$mysqli->connect_errno.')'.$mysqli->connect_error);
}

$result=$mysqli->query('select`id`,price,user_idfrom`order`');
$orders=$result->fetch_all(MYSQLI_ASSOC);

$userIds=implode(',',array_column($orders,'user_id'));//获取订单中的用户id
$result=$mysqli->query("select`id`,`name`from`user`whereidin({$userIds})");
$users=$result->fetch_all(MYSQLI_ASSOC);//获取这些用户的姓名

//将id做数组键
$userRes=[];
foreach($usersas$user){
$userRes[$user['id']]=$user['name'];
}

$res=[];
//整合数据
foreach($ordersas$order){
$current=[];
$current['id']=$order['id'];
$current['price']=$order['price'];
$current['name']=$userRes[$order['user_id']]?:'';
$res[]=$current;
}
var_dump($res);

//关闭mysql连接

$mysqli->close();
28bd9a28-779a-11ee-939d-92fbcf53809c.jpg

join

$mysqli=newmysqli('127.0.0.1','root','root','test');
if($mysqli->connect_error){
die('ConnectError('.$mysqli->connect_errno.')'.$mysqli->connect_error);
}

$result=$mysqli->query('selectorder.id,price,user.`name`from`order`joinuseronorder.user_id=user.id;');
$orders=$result->fetch_all(MYSQLI_ASSOC);

var_dump($orders);
$mysqli->close();
28cc54dc-779a-11ee-939d-92fbcf53809c.jpg

看时间的话,明显join更快一些

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud
  • 视频教程:https://doc.iocoder.cn/video/

三、试下多一些数据的情况

user表现在10000条数据,order表10000条试下

1、join

28d71b1a-779a-11ee-939d-92fbcf53809c.jpg

2、分开

order

28e1cbe6-779a-11ee-939d-92fbcf53809c.jpg

user

28f0428e-779a-11ee-939d-92fbcf53809c.jpg

3、代码层面

in

2902983a-779a-11ee-939d-92fbcf53809c.jpg

join

29180a4e-779a-11ee-939d-92fbcf53809c.jpg

三、试下多一些数据的情况

随机插入后user表十万条数据,order表一百万条试下

1、join

2927e5d6-779a-11ee-939d-92fbcf53809c.jpg

2、分开

order

2932ea80-779a-11ee-939d-92fbcf53809c.jpg

user

order查出来的结果过长了,,,

3、代码层面

in

293feea6-779a-11ee-939d-92fbcf53809c.jpg

join

294aab20-779a-11ee-939d-92fbcf53809c.jpg

四、到底怎么才能更好

注:对于本机来说100000条数据不少了,更大的数据量害怕电脑卡死

总的来说,当数据量小时,可能一页数据就够放的时候,join的成本和速度都更好。数据量大的时候确实分开查的成本更低,但是由于数据量大,造成循环的成本更多,代码执行的时间也就越长。

实验过程中发现,当in的数据量过大的时候,sql过长会无法执行,可能还要拆开多条sql进行查询,这样的查询成本和时间一定也会更长,而且如果有分页的需求的话,也无法满足。。。

感觉这两个方法都不是太好,各位小伙伴,有没有更好的方法呢?


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • MySQL
    +关注

    关注

    1

    文章

    775

    浏览量

    26005

原文标题:MySQL到底是 join 性能好,还是in一下更快呢?

文章出处:【微信号:芋道源码,微信公众号:芋道源码】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    到底是arduino还是51

    最近对arduino很感冒,对51单片机的热情降低了很多,到底是arduino还是51,有点点纠结。求助,帮小弟解析一下。谢谢了!
    发表于 05-23 22:29

    目前国产CPLD达到怎样水平了,有没有性能好的帮忙推荐一下

    目前国产CPLD达到怎样水平了,有没有性能好的帮忙推荐一下
    发表于 02-26 11:34

    PLC到底是什么

    PLC到底是什么
    发表于 10-10 09:30

    两层板设计晶振下方到底是挖空还是铺地

    请教给位大神,晶振下方到底是挖空还是铺地& p& V2 I/ Q- M# O比如说我两层板,顶层是贴片晶振,那么底层是挖空还是铺地
    发表于 12-26 11:55

    mysql中的7种JOIN

    mysqlJOIN大汇总
    发表于 03-11 11:18

    请问一下eMMC真能优化成UFS?手机闪存到底是指什么?

    请问一下eMMC真能优化成UFS?手机闪存到底是指什么?
    发表于 06-18 07:55

    请问一下在使用stm32 rtc的时候到底是选用LSI还是LSE?

    请问一下在使用stm32 rtc的时候到底是选用LSI还是LSE?
    发表于 09-23 06:16

    请问一下电脑的控制器到底是什么?

    请问一下电脑的控制器到底是什么?
    发表于 10-28 07:35

    到底是学STM32还是学嵌入式linux

    一下,希望对大家有所启发。02STM32确实首先得承认STM32确实,好到STM32都成了单片机MCU的代名词了,现在很多人甚至说单片机时默认就..
    发表于 11-04 08:50

    到底是学STM32还是学嵌入式linux

    01话 题经常有大学生同学纠结:我到底是学STM32还是学嵌入式linux。这个问题很多人都会有自己的看法,今天我试着从多个角度,把我了解到的事实讲一下,希望对大家有所启发。STM3202STM32
    发表于 02-07 07:06

    请问一下ARM Cortex A9的核心(4核心) 到底是多少HZ

    请问一下ARM Cortex A9的核心(4核心) 到底是多少HZ
    发表于 08-25 15:45

    应用层关联的优势 MySQL不推荐使用join的原因

    对于mysql,不推荐使用子查询和join是因为本身join的效率就是硬伤,一旦数据量很大效率就很难保证,强烈推荐分别根据索引单表取数据,然后在程序里面做join,merge数据。
    发表于 02-23 14:07 314次阅读

    如何优化MySQL中的join语句

    mysql中,join 主要有Nested Loop、Hash Join、Merge Join 这三种方式,我们今天来看一下最普遍 Nes
    的头像 发表于 04-24 17:03 574次阅读
    如何优化<b class='flag-5'>MySQL</b>中的<b class='flag-5'>join</b>语句

    单片机的“性能到底是什么?

    单片机的“性能到底是什么?
    的头像 发表于 10-24 16:58 284次阅读
    单片机的“<b class='flag-5'>性能</b>”<b class='flag-5'>到底是</b>什么?

    去耦滤波电容怎么布局摆放,到底是先大后小还是先小后大?

    去耦滤波电容怎么布局摆放,到底是先大后小还是先小后大?
    的头像 发表于 12-04 15:43 1378次阅读
    去耦滤波电容怎么布局摆放,<b class='flag-5'>到底是</b>先大后小<b class='flag-5'>还是</b>先小后大?