面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

这篇具有很好参考价值的文章主要介绍了面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

来源:https://juejin.cn/post/7169567387527282701

先总结:

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

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

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

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

一、表结构

1、用户表

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

 CREATE TABLE `user` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '姓名',
  `gender` smallint DEFAULT NULL COMMENT '性别',
  `mobile` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '手机号',
  `create_time` datetime NOT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `mobile` (`mobile`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1005 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

2、订单表

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

CREATE TABLE `order` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `price` decimal(18,2) NOT NULL,
  `user_id` int NOT NULL,
  `product_id` int NOT NULL,
  `status` smallint NOT NULL DEFAULT '0' COMMENT '订单状态',
  PRIMARY KEY (`id`),
  KEY `user_id` (`user_id`),
  KEY `product_id` (`product_id`)
) ENGINE=InnoDB AUTO_INCREMENT=202 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

推荐一个开源免费的 Spring Boot 实战项目:

https://github.com/javastacks/spring-boot-best-practice

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

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

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

下面从三个维度来看

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

1、join

JOIN:

explain format=json select order.id, price, user.`name` from `order` join user on order.user_id = user.id;

子查询:

select order.id,price,user.`name` from `order`,user where user_id=user.id;

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

2、分开查

select `id`,price,user_id from `order`;

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

select name from user where id in (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\]

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

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

3、代码层面

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

ab -n 100 -c 10

in
 $mysqli = new mysqli('127.0.0.1', 'root', 'root', 'test');
 if ($mysqli->connect_error) {
     die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
 }

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

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

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

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

 // 关闭mysql连接

 $mysqli->close();

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

join
$mysqli = new mysqli('127.0.0.1', 'root', 'root', 'test');
if ($mysqli->connect_error) {
    die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
}

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

var_dump($orders);
$mysqli->close();

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

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

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

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

1、join

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

2、分开

order

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

user

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

3、代码层面

in

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

join

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

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

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

1、join

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

2、分开

order

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

user

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

3、代码层面

in

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

join

面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…

四、到底怎么才能更好

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

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

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

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

参考资料:

https://www.cnblogs.com/zhuwenjoyce/p/14968183.html

https://blog.csdn.net/xjk201/article/details/122051216

https://juejin.cn/book/6844733769996304392/section/6844733770055024647

近期热文推荐:

1.1,000+ 道 Java面试题及答案整理(2022最新版)

2.劲爆!Java 协程要来了。。。

3.Spring Boot 2.x 教程,太全了!

4.别再写满屏的爆爆爆炸类了,试试装饰器模式,这才是优雅的方式!!

5.《Java开发手册(嵩山版)》最新发布,速速下载!

觉得不错,别忘了随手点赞+转发哦!文章来源地址https://www.toymoban.com/news/detail-760642.html

到了这里,关于面试官:MySQL 到底是 join 性能好,还是 in 一下更快呢?被问懵逼了…的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • MySQL性能优化盲区(高并发情况下,事务内的数据先更新还是先查询?)

    近期看到了一个前阿里资深开发的学术分析视频: 高并发情况下,一个事务内有更新操作还有查询操作,那是先更新好,还是先无锁查询好? 仅70秒的视频,深感学问太深,但是海哥讲的有待补充,于是写下了这篇文章,作为补充。 鸣谢:前阿里资深开发极海Channel的技术分

    2024年03月15日
    浏览(50)
  • 面试官:请说一下Mysql中count(1)、count(*)以及count(列)的区别?

    近期在Review项目代码时,发现同事们在查询MySQL行数时存在多样的方式,有的使用 COUNT(1) , 有的用 COUNT(id) , 还有人选择了 COUNT(*) 。这混杂的选择引发了我的思考。当然这三种count的方式也是众说纷纭,其中最大的分歧点就是 COUNT(*) 和 COUNT(1) 查询性能上,有人觉得 COUNT(*) 需要

    2024年02月19日
    浏览(39)
  • 面试被问麻了...

    前几天组了一个软件测试面试的群,没想到效果直接拉满,看来大家对面试这块的需求还是挺迫切的。昨天我就看到群友们发的一些面经,感觉非常有参考价值,于是我就问他还有没有。 结果他给我整理了一份非常硬核的面筋,打开一看,也太多了,差点麻了。。。 不过,

    2024年02月07日
    浏览(48)
  • 面试被问麻了....

    前几天组了一个软件测试面试的群,没想到效果直接拉满,看来大家对面试这块的需求还是挺迫切的。昨天我就看到群友们发的一些面经,感觉非常有参考价值,于是我就问他还有没有。 结果他给我整理了一份非常硬核的面筋,打开一看,也太多了,差点麻了。。。 不过,

    2024年02月05日
    浏览(42)
  • 面试真的被问麻了......

    前几天组了一个软件测试面试的群,没想到效果直接拉满,看来大家对面试这块的需求还是挺迫切的。昨天我就看到群友们发的一些面经,感觉非常有参考价值,于是我就问他还有没有。 结果他给我整理了一份非常硬核的面筋,打开一看,也太多了,差点麻了。。。 不过,

    2024年02月05日
    浏览(42)
  • 你好,面试官 | 阿里二面,被问麻了。。

    本期是【 你好,面试官 】系列文章的第 21 期,持续更新中…。 《你好,面试官》系列目前已经连载 20 篇了,据说看了这个系列的朋友都拿到了大厂offer~ 欢迎星标+订阅,持续更新中。。。致力打造校招核心面试攻略~ Java 校招面试网站:www.java2top.cn 本期考点涉及, JVM 、

    2024年02月05日
    浏览(42)
  • 到底叫 集合还是数组还是list还是列表?

    1 总体上可以将数据结构分为数组和集合两种,而列表是一个泛指 2 数组 -- 有序的,但长度是固定的-元素数量固定并且需要频繁访问,那么使用数组可能更合适 3 集合 3.1 list  -- 支持添加和删除元素,或者元素的数量不确定,就可以使用List类型 3.2 set -- Set是一种不允许重

    2024年02月14日
    浏览(39)
  • 面试被问到:测试计划和测试方案有什么区别?

    面试的时候,很多小伙伴都被面试官问过这个问题 “测试计划和测试方案有什么区别”? 到底有什么区别呢?我们先好好了解下这两个文档。 1、测试计划是什么? 测试计划是组织管理层面的文件,从组织管理的角度对一次测试活动进行规划。对测试全过程的测试范围、组

    2023年04月14日
    浏览(80)
  • 面试中常被问到sql优化几种方案

    目录 一、索引优化 二、合理的查询设计 三、分页优化: 四、内存管理和缓存: 五、合理使用批量操作: 六、使用连接池: 七、分区表: 八、避免使用SELECT : 九、数据库升级和优化器统计信息: 十、避免不必要的约束和触发器: 十一、使用EXPLAIN分析查询计划: 十二、

    2024年02月10日
    浏览(68)
  • 5年测试被裁,去面试差点被问哭了······

    我的个人背景非常简单,也可以说丝毫没有亮点。 学历普通,计算机专业二本毕业,毕业后出来就一直在一家小公司,岁月如梭细,算了下至今从事软件测试已经5年了,也点点点了五年,每天都是重复的工作,毫无新意,甚至一度的怀疑人生,后来就失业了,一度颓废了,

    2024年02月04日
    浏览(37)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包