首页 » 网站推广 » phpjoinon技巧_mysql到底是join机能好照样in一下更快呢

phpjoinon技巧_mysql到底是join机能好照样in一下更快呢

duote123 2024-10-29 0

扫一扫用手机浏览

文章目录 [+]

本日创造一篇很故意思的文章,利用 mysql 查询时,是利用 join 好,还是直接 in 更好,这个大家事情时常常碰着。

为了方便大家查看,文章我重新进行了排版。

phpjoinon技巧_mysql到底是join机能好照样in一下更快呢

我没有直接用作者的结论,觉得可能会误导读者,而是根据实验结果,给出我自己的建议。

phpjoinon技巧_mysql到底是join机能好照样in一下更快呢
(图片来自网络侵删)

话不多说,上目录:

01 背景

事情是这样的,去年入职的新公司,之后在代码 review 的时候被提出说,不要写 join,join 耗性能还是慢来着,当时也是真的没有多想,那就写 in 好了。

最近创造 in 的数据量过大的时候会导致 sql 慢,乃至 sql 太长,直接报错了。

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

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

02 表构造2.1 用户表

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_ci2.2 订单表

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_ci03 千条数据情形

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

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

耗时衡量指标:多表连接查询本钱 = 一次驱动表本钱 + 从驱动表查出的记录数 一次被驱动表的本钱

3.1 join

select order.id, price, user.name from order join user on order.user_id = user.id;

3.2 in

select id,price,user_id from order;

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。

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

3.3 并发场景

紧张用php原生写了脚本,用ab进行10个同时的要求,看下韶光,进行比较。

> ab -n 100 -c 10 // 实行脚本

下面是 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();

下面是 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();

看韶光的话,明显 join 更快一些。

04 万条数据情形

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

4.1 join

4.2 in

order 耗时:

user 耗时:

4.3 并发场景

join 耗时:

in 耗时:

数据量达到万级别,非并发场景,in 更快,并发场景 join 更快。

05 十万条数据情形

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

5.1 join

5.2 in

order 耗时:

user 耗时:

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

5.3 并发场景

join 耗时:

in 耗时:

数据量达到十万/百万级别,非并发场景,in 过长,并发场景 join 更快。

06 总结

实验结论:

数据量不到万级别,join 和 in 差不多;数据量达到万级别,非并发场景,in 更快,并发场景 join 更快;数据量达到十万/百万级别,非并发场景,in 过长,并发场景 join 更快。

下面是楼仔给出的一些建议。

当数据量比较小时,建议用 in,虽然两者的性能差不多,但是 join 会增加 sql 的繁芜度,后续再变更,会非常麻烦。

当数据量比较大时,建议用 join,紧张还是出于查询性能的考虑。

不过利用 join 时,小表驱动大表,一定要建立索引,join 的表最好不要超过 3 个,否则性能会非常差,还会大大增加 sql 的繁芜度,非常不利于后续功能扩展。

标签:

相关文章

Python编程从入门到精通,探索编程之美

编程已经成为现代社会的一项基本技能。Python作为一种简单易学、功能强大的编程语言,在我国教育领域备受关注。本文将从Python...

网站推广 2025-03-02 阅读1 评论0

Scum07代码编程之美与适用方法

编程已成为当今社会不可或缺的技能之一。Scum07代码作为一款经典的编程语言,在我国众多程序员中备受推崇。本文将深入解析Scum0...

网站推广 2025-03-02 阅读1 评论0

Linux环境下的前端代码运行优化与步骤

前端技术逐渐成为软件开发的核心。Linux操作系统因其稳定性、安全性、开放性等特点,成为众多开发者和企业青睐的运行环境。本文将从L...

网站推广 2025-03-02 阅读1 评论0