mysql 到底是 join性能好慎玖,還是in一下更快呢

先總結(jié):

  1. 數(shù)據(jù)量小的時(shí)候贮尖,用join更劃算
  2. 數(shù)據(jù)量大的時(shí)候,join的成本更高趁怔,但相對(duì)來說join的速度會(huì)更快
  3. 數(shù)據(jù)量過大的時(shí)候湿硝,in的數(shù)據(jù)量過多薪前,會(huì)有無法執(zhí)行SQL的問題,待解決

事情是這樣的关斜,去年入職的新公司示括,之后在代碼review的時(shí)候被提出說,不要寫join蚤吹,join耗性能還是慢來著例诀,當(dāng)時(shí)也是真的沒有多想,那就寫in好了裁着,最近發(fā)現(xiàn)in的數(shù)據(jù)量過大的時(shí)候會(huì)導(dǎo)致sql慢,甚至sql太長拱她,直接報(bào)錯(cuò)了二驰。這次來淺究一下,到底是in好還是join好秉沼,僅目前認(rèn)知探尋桶雀,有不對(duì)之處歡迎指正

以下實(shí)驗(yàn)僅在本機(jī)電腦試驗(yàn)

一、表結(jié)構(gòu)

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 '手機(jī)號(hào)',
  `create_time` datetime NOT NULL COMMENT '創(chuàng)建時(shí)間',
  PRIMARY KEY (`id`),
  UNIQUE KEY `mobile` (`mobile`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1005 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci

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 '訂單狀態(tài)',
  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

二、先來試少量數(shù)據(jù)的情況

用戶表插一千條隨機(jī)生成的數(shù)據(jù)敞咧,訂單表插一百條隨機(jī)數(shù)據(jù)

查下所有的訂單以及訂單對(duì)應(yīng)的用戶

下面從三個(gè)維度來看

多表連接查詢成本 = 一次驅(qū)動(dòng)表成本 + 從驅(qū)動(dòng)表查出的記錄數(shù) * 一次被驅(qū)動(dòng)表的成本

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;

2、分開查

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乍恐、代碼層面

主要用php原生寫了腳本,用ab進(jìn)行10個(gè)同時(shí)的請(qǐng)求测砂,看下時(shí)間茵烈,進(jìn)行比較

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做數(shù)組鍵
 $userRes = [];
 foreach ($users as $user) {
     $userRes[$user['id']] = $user['name'];
 }

 $res = [];
 // 整合數(shù)據(jù)
 foreach ($orders as $order) {
     $current = [];
     $current['id'] = $order['id'];
     $current['price'] = $order['price'];
     $current['name'] = $userRes[$order['user_id']] ?: '';
     $res[] = $current;
 }
 var_dump($res);

 // 關(guān)閉mysql連接

 $mysqli->close();
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();
復(fù)制代碼

看時(shí)間的話,明顯join更快一些

三砌些、試下多一些數(shù)據(jù)的情況

user表現(xiàn)在10000條數(shù)據(jù)呜投,order表10000條試下

1抡谐、join

2统屈、分開

user

3、代碼層面

in

join

三等限、試下多一些數(shù)據(jù)的情況

隨機(jī)插入后user表十萬條數(shù)據(jù)有巧,order表一百萬條試下

1释漆、join

2、分開

order

user

order查出來的結(jié)果過長了,,,

3篮迎、代碼層面

in

join

四男图、到底怎么才能更好

注:對(duì)于本機(jī)來說100000條數(shù)據(jù)不少了示姿,更大的數(shù)據(jù)量害怕電腦卡死

總的來說,當(dāng)數(shù)據(jù)量小時(shí)逊笆,可能一頁數(shù)據(jù)就夠放的時(shí)候栈戳,join的成本和速度都更好。數(shù)據(jù)量大的時(shí)候確實(shí)分開查的成本更低难裆,但是由于數(shù)據(jù)量大子檀,造成循環(huán)的成本更多,代碼執(zhí)行的時(shí)間也就越長乃戈。實(shí)驗(yàn)過程中發(fā)現(xiàn)褂痰,當(dāng)in的數(shù)據(jù)量過大的時(shí)候,sql過長會(huì)無法執(zhí)行症虑,可能還要拆開多條sql進(jìn)行查詢缩歪,這樣的查詢成本和時(shí)間一定也會(huì)更長,而且如果有分頁的需求的話谍憔,也無法滿足匪蝙。。习贫。

感覺這兩個(gè)方法都不是太好逛球,各位小伙伴,有沒有更好的方法呢苫昌?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末颤绕,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蜡歹,更是在濱河造成了極大的恐慌屋厘,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件月而,死亡現(xiàn)場(chǎng)離奇詭異汗洒,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)父款,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門溢谤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人憨攒,你說我怎么就攤上這事世杀。” “怎么了肝集?”我有些...
    開封第一講書人閱讀 165,871評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵瞻坝,是天一觀的道長。 經(jīng)常有香客問我杏瞻,道長所刀,這世上最難降的妖魔是什么衙荐? 我笑而不...
    開封第一講書人閱讀 58,963評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮浮创,結(jié)果婚禮上忧吟,老公的妹妹穿的比我還像新娘。我一直安慰自己斩披,他們只是感情好溜族,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,984評(píng)論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著垦沉,像睡著了一般煌抒。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乡话,一...
    開封第一講書人閱讀 51,763評(píng)論 1 307
  • 那天摧玫,我揣著相機(jī)與錄音,去河邊找鬼绑青。 笑死,一個(gè)胖子當(dāng)著我的面吹牛屋群,可吹牛的內(nèi)容都是我干的闸婴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼芍躏,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼邪乍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起对竣,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤庇楞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后否纬,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吕晌,經(jīng)...
    沈念sama閱讀 45,850評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,002評(píng)論 3 338
  • 正文 我和宋清朗相戀三年临燃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了睛驳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,144評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡膜廊,死狀恐怖乏沸,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情爪瓜,我是刑警寧澤蹬跃,帶...
    沈念sama閱讀 35,823評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站铆铆,受9級(jí)特大地震影響蝶缀,放射性物質(zhì)發(fā)生泄漏丹喻。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,483評(píng)論 3 331
  • 文/蒙蒙 一扼劈、第九天 我趴在偏房一處隱蔽的房頂上張望驻啤。 院中可真熱鬧,春花似錦荐吵、人聲如沸骑冗。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贼涩。三九已至,卻和暖如春薯蝎,著一層夾襖步出監(jiān)牢的瞬間遥倦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評(píng)論 1 272
  • 我被黑心中介騙來泰國打工占锯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留袒哥,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,415評(píng)論 3 373
  • 正文 我出身青樓消略,卻偏偏與公主長得像堡称,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艺演,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,092評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容