成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

數據庫 MySQL
不過使用 join 時,小表驅動大表,一定要建立索引,join 的表最好不要超過 3 個,否則性能會非常差,還會大大增加 sql 的復雜度,非常不利于后續功能擴展。

大家好呀,我是樓仔。

今天發現一篇很有意思的文章,使用 mysql 查詢時,是使用 join 好,還是直接 in 更好,這個大家工作時經常遇到。

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

我沒有直接用作者的結論,感覺可能會誤導讀者,而是根據實驗結果,給出我自己的建議。

不 BB,上目錄:

圖片圖片

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_ci

2.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_ci

03 千條數據情況

數據量:用戶表插一千條隨機生成的數據,訂單表插一百條隨機數據

要求:查下所有的訂單以及訂單對應的用戶

耗時衡量指標:多表連接查詢成本 = 一次驅動表成本 + 從驅動表查出的記錄數 * 一次被驅動表的成本

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 的復雜度,非常不利于后續功能擴展。

責任編輯:武曉燕 來源: 樓仔
相關推薦

2023-12-01 08:27:53

MySQLjoin

2018-10-09 15:26:19

JavaPython語言

2018-09-26 14:17:00

編程語言JavaPython

2024-03-15 08:06:58

MySQLJOIN命令

2019-02-14 14:09:09

散熱器水冷一體式

2023-10-09 22:18:28

Python強制縮進

2021-08-31 07:54:24

TCPIP協議

2015-04-21 09:20:40

SwfitObject—C

2024-03-28 13:13:00

Htmx前端開發框架

2017-08-09 08:43:02

公有云趨勢聲勢

2011-09-05 10:30:51

重構代碼庫業務模型

2014-11-17 10:03:23

OpenStack

2022-08-18 23:13:25

零信任安全勒索軟件

2014-06-05 14:46:05

設計設計師

2021-12-09 20:16:26

無線核心網傳輸

2020-08-31 19:19:27

TCPUDP視屏面試

2023-10-10 16:03:48

數字化信息化

2020-10-19 09:51:18

MYSQL知識數據庫

2020-06-02 10:38:15

IDEiOSLinux

2020-08-31 19:17:24

Python強類型語言弱類型語言
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 亚洲一二视频 | 精品婷婷| 亚洲综合视频 | 国产日韩亚洲欧美 | 亚洲v日韩v综合v精品v | av不卡一区 | 五月婷婷丁香婷婷 | 久久蜜桃av一区二区天堂 | 亚洲欧美日韩精品久久亚洲区 | 久色一区 | 久久久久久久久淑女av国产精品 | 免费在线观看av片 | 欧美黄色片| 亚洲精品在线看 | 欧美国产日韩在线观看成人 | 91精品国产91 | 一区二区三区亚洲 | 中文字幕欧美一区 | 午夜免费视频 | 黄色一级毛片免费看 | 精品欧美乱码久久久久久 | 日韩视频在线免费观看 | 亚洲天堂一区二区 | 日日夜夜av | 欧美日韩精品免费 | www.99热这里只有精品 | 精品一二三 | 国产精品久久久久久久久久久久久 | 国产激情网 | 欧美一区二区三区 | h片在线免费观看 | 日韩成人av在线播放 | 国产成人午夜精品影院游乐网 | 在线视频成人 | 精品久久香蕉国产线看观看亚洲 | 网站国产 | 黄色成人免费在线观看 | 亚洲成人一区二区在线 | av一二三四 | 久久一区二区三区四区 | 久久大陆 |