偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

面試官:你們的項目中竟然還在用多表關(guān)聯(lián)!

數(shù)據(jù)庫 其他數(shù)據(jù)庫
可用性提升,如果驅(qū)動表有10萬條數(shù)據(jù),而被驅(qū)動表也有10萬條,哪怕在QPS為個位數(shù)的情況下,都可能將數(shù)據(jù)庫的網(wǎng)卡打滿,從而出現(xiàn)系統(tǒng)不可用的情況。

本文中我們繼續(xù)介紹Hash Join(哈希連接),以及從技術(shù)原理的角度上給出最終結(jié)論 —— 我們還是應(yīng)該在數(shù)據(jù)庫中合理使用多表關(guān)聯(lián)查詢,而不是放到應(yīng)用程序中。

圖片圖片

我們在上一篇文章中說過,從MySQL 8.0.20開始,就不再使用緩存塊嵌套循環(huán)連接了,將以前使用緩存塊嵌套循環(huán)連接的場景全部改為哈希連接。

因為在絕大多數(shù)被驅(qū)動表沒有創(chuàng)建索引的場景,哈希連接比緩存塊嵌套循環(huán)連接性能更高。

MySQL表連接算法

哈希連接(Hash Join)

市面上所有支持哈希連接算法的數(shù)據(jù)庫,無論是OLTP數(shù)據(jù)庫中的Oracle,還是OLAP數(shù)據(jù)庫中的ClickHouse、Doris,其實現(xiàn)方式都是將小表加載到內(nèi)存形成哈希表,再通過遍歷大表數(shù)據(jù)的方式與哈希表進行匹配,并返回匹配結(jié)果。

MySQL的實現(xiàn)方式也不例外,我們以下面的SQL語句舉例:

SELECT * FROM product p INNER JOIN order o 
ON p.id = o.product_id WHERE p.id in(1,2);

圖片圖片

Using where; Using join buffer (hash join)
SELECT * FROM product p INNER JOIN order o 
ON p.id = o.product_id WHERE p.id in(1,2);
SELECT * FROM t1 JOIN t2 ON t1.c1 < t2.c1
SELECT * FROM t1 WHERE t1.c1 IN (SELECT t2.c2 FROM t2)

Antijoin:

SELECT * FROM t2 WHERE NOT EXISTS (SELECT * FROM t1 WHERE 
t1.c1 = t2.c1)

Left outer join:

SELECT * FROM t1 LEFT JOIN t2 ON t1.c1 = t2.c1

Right outer join:

SELECT * FROM t1 RIGHT JOIN t2 ON t1.c1 = t2.c1

應(yīng)用程序表連接算法

接下來開始聊重頭戲了,我們看一下,如果真的禁止使用SQL語句進行多表關(guān)聯(lián),而是把各表的數(shù)據(jù)讀到應(yīng)用程序中來,再由程序進行數(shù)據(jù)merge操作,這該如何實現(xiàn)呢?

圖片圖片

步驟其實很簡單,從product表和order表中分別讀出數(shù)據(jù)后,在應(yīng)用程序代碼中要么通過一個大嵌套循環(huán)來進行表數(shù)據(jù)的連接匹配,要么通過一個HashMap進行表的連接列匹配,跟MySQL中的實現(xiàn)基本上大同小異。

數(shù)據(jù)庫 VS 應(yīng)用程序

那么,到底是放在數(shù)據(jù)庫中實現(xiàn)多表關(guān)聯(lián)查詢比較好,還是放到應(yīng)用程序中比較好呢?

贊成后者的同學(xué)會說,數(shù)據(jù)庫是一個極為寶貴稀缺的資源,而應(yīng)用服務(wù)器我們可以以集群部署的方式無限擴容。因此,將多表關(guān)聯(lián)操作放到應(yīng)用服務(wù)器中可以減輕數(shù)據(jù)庫的壓力。

對于這種說法,我只能說:“呵呵,數(shù)據(jù)庫的主從復(fù)制了解一下?不僅可以搭從庫,還可以搭二級從庫呢?!?/p>

還有一種贊成后者說法是,單表查詢在應(yīng)用程序中進行merge,這樣更有利于后續(xù)的維護,并且代碼復(fù)用性高。

原因在于,SQL語句寫得越簡單,那就越容易被復(fù)用,而多表關(guān)聯(lián)的復(fù)雜SQL只能有一種應(yīng)用場景。

這種說法就相當(dāng)于,把香河肉餅變成面粉、肉餡和食用油之后復(fù)用性高了,因為面粉可以蒸饅頭烙餅、肉餡可以做包子和餃子,而食用油則可以炒任何菜。

最離譜的一種說法是,放到應(yīng)用服務(wù)器中進行merge操作,性能會高一些。

對于這種說法,我只想說,到底是梁靜茹給你的勇氣,張信哲給你的信仰,還是五月天給你的倔強呢?

你能在表連接算法優(yōu)化上比數(shù)據(jù)庫研發(fā)者做得更好?我怎么就這么不信呢?

接下來,我說說贊成后者的原因吧,有如下三點:

(1)研發(fā)效率更高,畢竟一條SQL語句就可以搞定的事情,沒必要寫完SQL再寫代碼,兩邊兒一起忙活。

(2)代碼性能更快,如果驅(qū)動表有1萬條數(shù)據(jù),而被驅(qū)動表也有1萬條,兩者關(guān)聯(lián)到一起后返回10條數(shù)據(jù)。這種場景下,到底是哪種方式更快一些,應(yīng)該顯然易見了吧?

畢竟把兩表中的各1萬條數(shù)據(jù)通過網(wǎng)絡(luò)返回給應(yīng)用服務(wù)器,再加載到內(nèi)存中進行merge,這些都是比較耗費性能的操作。

(3)可用性提升,如果驅(qū)動表有10萬條數(shù)據(jù),而被驅(qū)動表也有10萬條,哪怕在QPS為個位數(shù)的情況下,都可能將數(shù)據(jù)庫的網(wǎng)卡打滿,從而出現(xiàn)系統(tǒng)不可用的情況。

這種故障場景,我還真的在實際工作中遇到過,當(dāng)時整整掛了一個多小時呢。

責(zé)任編輯:武曉燕 來源: 托尼學(xué)長
相關(guān)推薦

2019-11-19 16:10:24

面試官Java編程語言

2023-01-26 00:25:09

JVM設(shè)置技術(shù)

2024-09-24 16:30:46

分布式鎖Redis數(shù)據(jù)中間件

2021-09-15 07:56:32

TypeScriptVue項目

2021-09-14 07:06:13

React項目TypeScript

2021-04-12 21:34:29

Redis故障數(shù)據(jù)

2024-09-25 17:44:08

2022-07-12 12:05:22

JavaSemaphore

2025-06-13 02:10:00

MySQL大表業(yè)務(wù)場景

2015-08-13 10:29:12

面試面試官

2019-10-21 09:56:37

MySQLCOUNTInnoDB

2021-04-14 18:58:01

虛擬機 Java內(nèi)存

2021-09-29 19:17:51

編碼URLEncodeGBK

2022-05-23 08:43:02

BigIntJavaScript內(nèi)置對象

2025-04-01 00:00:00

項目CRUD單例模式

2021-11-08 15:59:01

MyBatis關(guān)聯(lián)開發(fā)

2025-02-26 12:19:52

2025-03-10 11:48:22

項目服務(wù)設(shè)計

2010-08-12 16:28:35

面試官

2024-04-29 06:41:04

項目面試官QPS
點贊
收藏

51CTO技術(shù)棧公眾號