新聞中心
數(shù)據(jù)庫 join 是常用的查詢操作之一,它是將兩個(gè)或多個(gè)表中的數(shù)據(jù)進(jìn)行關(guān)聯(lián)的過程,可以通過這種方式獲取到更加豐富的數(shù)據(jù)信息。不過,如果 join 的效率不高,會(huì)導(dǎo)致大量的時(shí)間和資源浪費(fèi),降低數(shù)據(jù)庫的性能和應(yīng)用的響應(yīng)速度。因此,就變得非常重要了。

創(chuàng)新互聯(lián)公司服務(wù)項(xiàng)目包括渝水網(wǎng)站建設(shè)、渝水網(wǎng)站制作、渝水網(wǎng)頁制作以及渝水網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢(shì)、行業(yè)經(jīng)驗(yàn)、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機(jī)構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,渝水網(wǎng)站推廣取得了明顯的社會(huì)效益與經(jīng)濟(jì)效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到渝水省份的部分城市,未來相信會(huì)繼續(xù)擴(kuò)大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
本文將從以下幾個(gè)方面探討:
1. 設(shè)計(jì)合理的表結(jié)構(gòu)
2. 使用合適的 join 類型
3. 使用索引優(yōu)化 join
4. 減少 join 表的大小
5. 避免在 join 條件中使用函數(shù)
6. 避免使用子查詢
1. 設(shè)計(jì)合理的表結(jié)構(gòu)
合理的表結(jié)構(gòu)設(shè)計(jì)是數(shù)據(jù)庫性能優(yōu)化的關(guān)鍵之一,它可以直接影響到 join 的效率。在設(shè)計(jì)表結(jié)構(gòu)時(shí),需要根據(jù)實(shí)際業(yè)務(wù)需求,將數(shù)據(jù)盡可能地拆分到不同的表中,避免一個(gè)表中包含過多的字段和數(shù)據(jù),從而減少 join 操作中的數(shù)據(jù)量,提高查詢效率。
此外,在設(shè)計(jì)表結(jié)構(gòu)時(shí)還需要注意表之間的關(guān)聯(lián),盡量使用外鍵來建立關(guān)聯(lián)關(guān)系,這樣可以更加方便地進(jìn)行 join 操作,并且還能提高查詢的準(zhǔn)確性。
2. 使用合適的 join 類型
不同的 join 類型對(duì)查詢效率影響很大,因此需要根據(jù)實(shí)際需求選擇適合的 join 類型。下面簡要介紹一下幾種常見的 join 類型:
內(nèi)連接(INNER JOIN):對(duì)兩個(gè)表中的數(shù)據(jù)進(jìn)行匹配,僅返回匹配成功的數(shù)據(jù)。INNER JOIN 的查詢效率較高,但是無法查詢到?jīng)]有匹配的數(shù)據(jù)。
左連接(LEFT JOIN):返回左表中的所有數(shù)據(jù),同時(shí)包含與右表匹配的數(shù)據(jù),沒有匹配成功的右表數(shù)據(jù)用 NULL 填充。LEFT JOIN 的查詢效率較高,但是會(huì)增加查詢的數(shù)據(jù)量。
右連接(RIGHT JOIN):返回右表中的所有數(shù)據(jù),同時(shí)包含與左表匹配的數(shù)據(jù),沒有匹配成功的左表數(shù)據(jù)用 NULL 填充。RIGHT JOIN 的查詢效率較低,而且并不是所有的數(shù)據(jù)庫都支持 RIGHT JOIN。
全連接(FULL OUTER JOIN):返回兩個(gè)表中所有的數(shù)據(jù),并進(jìn)行匹配。如果某一方?jīng)]有匹配成功,則用 NULL 填充。FULL OUTER JOIN 的查詢效率較低,而且并不是所有的數(shù)據(jù)庫都支持 FULL OUTER JOIN。
3. 使用索引優(yōu)化 join
索引是優(yōu)化 join 查詢效率的重要手段,可以大幅提高查詢效率。在進(jìn)行 join 操作前,需要為 join 的依據(jù)字段創(chuàng)建合適的索引,包括主鍵索引、唯一索引、普通索引等。不過,需要注意避免創(chuàng)建過多的索引,否則會(huì)降低數(shù)據(jù)庫的性能。
4. 減少 join 表的大小
在進(jìn)行 join 操作時(shí),會(huì)將連接的表中的所有數(shù)據(jù)都加載到內(nèi)存中,如果表的大小太大,那么 join 的效率就會(huì)非常低,甚至?xí)?dǎo)致內(nèi)存不足的問題。因此,可以通過一些方式來減小 join 表的大小,例如分區(qū)或者分片、刪除過期數(shù)據(jù)、歸檔歷史數(shù)據(jù)等。
5. 避免在 join 條件中使用函數(shù)
在 join 的條件中使用函數(shù)會(huì)導(dǎo)致數(shù)據(jù)庫無法使用索引,從而降低查詢效率。因此,應(yīng)該盡量避免在 join 條件中使用函數(shù),可以將需要計(jì)算的值先計(jì)算出來,再將結(jié)果作為 join 條件。
6. 避免使用子查詢
子查詢是有些情況下必要的,但是過多使用會(huì)導(dǎo)致查詢效率降低。在 join 中盡量避免使用子查詢作為條件,可以通過改變查詢的方式,將子查詢的功能轉(zhuǎn)換為 join 查詢。
:
通過以上幾個(gè)方面的優(yōu)化,可以有效提高數(shù)據(jù)庫 join 的效率,提升系統(tǒng)的性能和響應(yīng)速度。在實(shí)際應(yīng)用中,還可以根據(jù)具體情況進(jìn)行優(yōu)化,不斷探索更加有效的優(yōu)化方式。
相關(guān)問題拓展閱讀:
- 使用MySQL的遞延Join連接實(shí)現(xiàn)高效分頁 – Aaron
- sql語句中 用 inner join 連接兩張表,大表放在前面比較快還是小表放在前面比較快。
使用MySQL的遞延Join連接實(shí)現(xiàn)高效分頁 – Aaron
在 Web 應(yīng)用程序中跨大型數(shù)據(jù)集分頁記錄似乎是一個(gè)簡單的問題,但實(shí)際上很難擴(kuò)展。兩種主要的分頁策略是偏移/限制和游標(biāo)。
我們將首先看一下這兩種方法,然后稍作修改,可以使偏移/限制非常高效。
偏移/限制分頁
偏移/限制方法是迄今為止最常見的方法,它通過跳過一定數(shù)量的記錄(頁)并將結(jié)果限制為一頁來工作。
例如,假設(shè)您的應(yīng)用程序配置為每頁顯示 15 條記錄。您的 SQL 將如下所示:
這是最常見的,因?yàn)樗浅:唵?,易于推理,并且?guī)缀趺總€(gè)框架都支持它。
除了易于實(shí)現(xiàn)之外,它還具有頁面可直接尋址的優(yōu)點(diǎn)。例如,如果您想直接導(dǎo)航到第 20 頁,您可以這樣做,因?yàn)樵撈屏亢苋菀子?jì)算。
但是有一個(gè)主要的缺點(diǎn),它潛伏在數(shù)據(jù)庫處理偏移量尺雀的方式中。偏移量告訴數(shù)據(jù)庫放棄從查詢中返回的前N個(gè)結(jié)果。不過數(shù)據(jù)庫仍然要從磁盤上獲取這些行。
如果你丟棄的是100條記錄,這并不重要,但如果你丟棄的是100,000條記錄,數(shù)據(jù)庫就會(huì)為了丟棄這些結(jié)果而做大量的工作。
在實(shí)踐中,這意味著之一個(gè)頁面會(huì)快速加載,之后的每一個(gè)頁面都會(huì)變得越來越慢,直到你達(dá)到一個(gè)點(diǎn),網(wǎng)絡(luò)請(qǐng)求可能會(huì)直接超時(shí)。
基于游標(biāo)的分頁
基于游標(biāo)的分頁彌補(bǔ)了偏移/限制的一些不足,同時(shí)引入了一些自己的不足。
基于游標(biāo)的分頁是通過存儲(chǔ)一些關(guān)于最后呈現(xiàn)給用戶態(tài)滾的記錄的狀態(tài),然后根據(jù)這個(gè)狀態(tài)來進(jìn)行下一次查詢。
因此,它不是按順序獲取所有的記錄并丟棄前N條,而是只獲取最后一個(gè)位置N之后的記錄。
如果按ID排序,SQL可能看起來像這樣。
你可能已經(jīng)看到了其中的好處。因?yàn)槲覀冎郎洗蜗蛴脩粽故镜腎D,我們知道下一個(gè)頁面將以一個(gè)更高的ID開始。我們甚至不需要檢查ID較低的行,因?yàn)槲覀儼俜种倏隙ǖ刂滥切┬胁恍枰伙@示。
在上面的例子中,我特別說明了ID可能不帆困余是連續(xù)的,也就是說,可能有缺失的記錄。這使得我們無法計(jì)算出哪些記錄會(huì)出現(xiàn)在某一頁面上,你必須跟蹤之前那一頁面上的最后一條記錄是什么。
與偏移/限制分頁不同,使用游標(biāo)分頁時(shí),頁面不能直接尋址,你只能導(dǎo)航到 “下一頁 “或 “上一頁”。
不過光標(biāo)分頁的好處是在任何數(shù)量的頁面上都很迅速。它也很適合無限滾動(dòng),在這種情況下,頁面首先不需要可以直接尋址。
Laravel文檔中有一些關(guān)于偏移量和游標(biāo)之間的權(quán)衡的好的背景。
cursor
-vs-offset-pagination
考慮到所有這些,讓我們來看看一個(gè)偏移/限制優(yōu)化,可以使它的性能足以在成千上萬的頁面上使用。
使用遞延join的Offset/Limit
遞延連接(deferred join )是一種技術(shù),它將對(duì)要求的列的訪問推遲到應(yīng)用了偏移量和限制之后。
使用這種技術(shù),我們創(chuàng)建一個(gè)內(nèi)部查詢,可以用特定的索引進(jìn)行優(yōu)化,以獲得更大的速度,然后將結(jié)果連接到同一個(gè)表,以獲取完整的行。
它看起來像這樣:
這種方法的好處可以根據(jù)你的數(shù)據(jù)集有很大的不同,但是這種方法允許數(shù)據(jù)庫盡可能少地檢查數(shù)據(jù),以滿足用戶的意圖。
查詢中 “昂貴的 “select *部分只在與內(nèi)部查詢相匹配的15條記錄上運(yùn)行。所有數(shù)據(jù)的Select都被推遲了,因此被稱為推遲join。
這種方法不太可能比傳統(tǒng)的偏移/限制性能差,盡管它是可能的,所以一定要在你的數(shù)據(jù)上進(jìn)行測(cè)試!
Laravel實(shí)現(xiàn)
我們?nèi)绾伟堰@一點(diǎn)帶到我們最喜歡的網(wǎng)絡(luò)框架,如Laravel和Rails?
讓我們具體看看Laravel,因?yàn)槲也恢繰ails。
感謝Laravel的macroable特性,我們可以擴(kuò)展Eloquent Query Builder來添加一個(gè)新的方法,叫做deferredPaginate。為了保持一致性,我們將模仿常規(guī)分頁的簽名。
我們將嘗試做盡可能少的自定義工作,并將大部分工作留給 Laravel。
這是我們要做的:
這應(yīng)該為我們提供 LaravelLengthAwarePaginator 和延遲連接的所有好處!
一個(gè)Github倉庫
遞延Join和覆蓋索引
還沒有完成…
使用遞延Join的主要好處是減少了數(shù)據(jù)庫必須檢索然后丟棄的數(shù)據(jù)量。我們可以通過幫助數(shù)據(jù)庫獲得它需要的數(shù)據(jù)而更進(jìn)一步,而無需獲取底層行。
這樣做的方法稱為“覆蓋索引covering index”,它是確??焖倨?限制分頁的最終解決方案。
覆蓋索引是一個(gè)索引,在這個(gè)索引中,查詢的所有需要的字段都包含在索引本身中。當(dāng)一個(gè)查詢的所有部分都能被一個(gè)索引 “覆蓋 “時(shí),數(shù)據(jù)庫根本不需要讀取該行,它可以從索引中獲得它需要的一切。
請(qǐng)注意,覆蓋索引并不是以任何特殊方式創(chuàng)建的。它只是指一個(gè)索引滿足了一個(gè)查詢所需要的一切的情況。一個(gè)查詢上的覆蓋索引很可能不是另一個(gè)查詢上的覆蓋索引。
在接下來的幾個(gè)例子中,我們將使用這個(gè)基本的表,我把它填滿了~1000萬條記錄。
讓我們看一個(gè)僅select索引列的簡單查詢。在這種情況下,我們將從email表中進(jìn)行select contacts。
在這種情況下,數(shù)據(jù)庫根本不需要讀取基礎(chǔ)行。在MySQL中,我們可以通過運(yùn)行一個(gè)解釋并查看額外的列來驗(yàn)證這一點(diǎn):
extra: using index告訴我們,MySQL能夠只使用索引來滿足整個(gè)查詢,而不看基礎(chǔ)行。
如果嘗試select name from contacts limit 10, 我們將期望MySQL必須到該行去獲取數(shù)據(jù),因?yàn)槊謓ame沒有被索引。這正是發(fā)生的情況,由下面的解釋顯示。
extra不再顯示 using index,所以我們沒有使用覆蓋索引。
假設(shè)你每頁有15條記錄,你的用戶想查看第1001頁,你的內(nèi)部查詢最終會(huì)是這樣的。
select id from contacts order by id limit 15 OFFSET
explain結(jié)果顯示:
MySQL能夠單看索引來執(zhí)行這個(gè)查詢。它不會(huì)簡單地跳過前15萬行,在使用offset是沒有辦法的,但它不需要讀取15萬行。(只有游標(biāo)分頁可以讓你跳過所有的行)。
即使使用覆蓋索引和延遲連接,當(dāng)你到達(dá)后面的頁面時(shí),結(jié)果也會(huì)變慢,盡管與傳統(tǒng)的偏移/限制相比,它應(yīng)該是最小的。使用這些方法,你可以輕易地深入到數(shù)千頁。
更好的覆蓋索引
這里的很多好處取決于擁有良好的覆蓋索引,所以讓我們稍微討論一下。一切都取決于您的數(shù)據(jù)和用戶的使用模式,但是您可以采取一些措施來確保查詢的更高命中率。
這將主要與 MySQL 對(duì)話,因?yàn)槟鞘俏矣薪?jīng)驗(yàn)的地方。其他數(shù)據(jù)庫中的情況可能會(huì)有所不同。
大多數(shù)開發(fā)人員習(xí)慣于為單列添加索引,但沒有什么能阻止您向多列添加索引。事實(shí)上,如果您的目標(biāo)是為昂貴的分頁查詢創(chuàng)建覆蓋索引,您幾乎肯定需要一個(gè)多列索引。
當(dāng)你試圖為分頁優(yōu)化一個(gè)索引時(shí),一定要把按列排序放在最后。如果你的用戶要按update_at排序,這應(yīng)該是你復(fù)合索引中的最后一列。
看看下面這個(gè)包括三列的索引。
在MySQL中,復(fù)合索引是從左到右訪問的,如果一個(gè)列缺失,或者在之一個(gè)范圍條件之后,MySQL會(huì)停止使用一個(gè)索引。
MySQL 將能夠在以下場(chǎng)景中使用該索引:
如果你跳過is_archived,MySQL將無法訪問update_at,將不得不訴諸于沒有該索引的排序,或者根本不使用該索引,所以要確保你有相應(yīng)的計(jì)劃。
主鍵始終存在
在MySQL的InnoDB中,所有的索引都附加了主鍵。這意味著(email)的索引實(shí)際上是(email,id)的索引,當(dāng)涉及到覆蓋索引和延遲連接時(shí),這是相當(dāng)重要的。
查詢select email from contacts order by id完全被email上的一個(gè)索引所覆蓋,因?yàn)镮nnoDB將id附加到了該索引上。
使用我們上面的綜合例子,你可以看到這有什么好處。
因?yàn)閺?fù)合索引涵蓋了is_deleted, is_archived, updated_at, 和(通過InnoDB的功能)id,整個(gè)查詢可以僅由索引來滿足。
降序索引
大多數(shù)時(shí)候,用戶都在尋找 “最新的 “項(xiàng)目,即最近更新或創(chuàng)建的項(xiàng)目,這可以通過按update_at DESC排序來滿足。
如果你知道你的用戶主要是以降序的方式對(duì)他們的結(jié)果進(jìn)行排序,那么特別將你的索引設(shè)為降序索引可能是有意義的。
MySQL 8是之一個(gè)支持降序索引的MySQL版本。
如果你在explain的Extra部分看到向后索引掃描,你也許可以配置一個(gè)更好的索引。
前向索引掃描比后向掃描快~15%,所以你要按照你認(rèn)為你的用戶最常使用的順序添加索引,并為少數(shù)使用情況承擔(dān)懲罰。
太陽底下無新事
這種使用偏移/限制分頁與延遲連接和覆蓋索引的方法并不是銀彈。
僅僅是遞遲連接就可以讓你的速度得到很好的提升,但是需要花一些額外的心思來設(shè)計(jì)正確的索引以獲得更大的好處。
有一種觀點(diǎn)認(rèn)為,遞延連接應(yīng)該是框架中默認(rèn)的偏移offset/限制limit方法,而任何時(shí)候覆蓋索引的出現(xiàn)都只是一種獎(jiǎng)勵(lì)。我還沒有在足夠多的生產(chǎn)環(huán)境中測(cè)試過,所以還沒有強(qiáng)烈主張這樣做。
使用MySQL的遞延Join連接實(shí)現(xiàn)高效分頁 – Aaron
sql語句中 用 inner join 連接兩張表,大表放在前面比較快還是小表放在前面比較快。
暈,你就連接兩張表,要什么速度快啊,一般把大表放在前面!
小表在前可以提高sql執(zhí)行效率。
首先將大表放在前面,即如圖(tmp2表數(shù)據(jù)量為40億,tmp1數(shù)據(jù)量只有81條),這樣執(zhí)行時(shí)間為3小時(shí)21分鐘,然后再將小表放在前面,執(zhí)行速度為10分鐘。
擴(kuò)展資料:
結(jié)構(gòu)化查詢語言
包含6個(gè)部分:
1、數(shù)據(jù)查詢語言(DQL:Data Query Language):其語句,也稱為“數(shù)據(jù)檢索語句”,用以從表中獲得數(shù)據(jù),確定數(shù)據(jù)怎樣在
應(yīng)用程序
給出。
保留字SELECT是乎鉛DQL(也是所有SQL)用得最多的動(dòng)詞,其他DQL常用的保留字有WHERE,ORDER BY,
GROUP BY
和HAVING。這些DQL保留字常與其它類型的SQL語句一起使用。
2、數(shù)據(jù)操作歲歲好語言(DML:Data Manipulation Language):其語句包括動(dòng)詞INSERT、UPDATE和DELETE。它們分別用于添加、修改和刪除。
3、事務(wù)控制語言(TCL):它的語句能確保被DML語句影響的表的所有行及時(shí)得以更新。包括COMMIT(提交)命令、SAVEPOINT(保存雀寬點(diǎn))命令、ROLLBACK(回滾)命令。
4、數(shù)據(jù)控制語言(DCL):它的語句通過GRANT或REVOKE實(shí)現(xiàn)權(quán)限控制,確定單個(gè)用戶和用戶組對(duì)數(shù)據(jù)庫對(duì)象的訪問。某些RDBMS可用GRANT或REVOKE控制對(duì)表單個(gè)列的訪問。
5、數(shù)據(jù)定義語言(DDL):其語句包括動(dòng)詞CREATE,ALTER和DROP。在數(shù)據(jù)庫中創(chuàng)建新表或修改、刪除表(CREAT TABLE 或 DROP TABLE);為表加入索引等。
6、指針控制語言(CCL):它的語句,像DECLARE CURSOR,F(xiàn)ETCH INTO和UPDATE WHERE CURRENT用于對(duì)一個(gè)或多個(gè)表單獨(dú)行的操作。
參考資料:
百度百科——sql語句
一樣快。因?yàn)镮nner join是不分主從表的,結(jié)果是取兩個(gè)表針對(duì)On條扒數(shù)件相匹配的最小集。
5G的表,得需要多大的服毀腔務(wù)器資源來處理?
建議春余首你首先針對(duì)兩張表做Where條件篩選,然后再做Join。
一樣的。應(yīng)該是同時(shí)檢索,做好用存儲(chǔ)過程會(huì)快點(diǎn)。
關(guān)于數(shù)據(jù)庫 join 效率的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
創(chuàng)新互聯(lián)服務(wù)器托管擁有成都T3+級(jí)標(biāo)準(zhǔn)機(jī)房資源,具備完善的安防設(shè)施、三線及BGP網(wǎng)絡(luò)接入帶寬達(dá)10T,機(jī)柜接入千兆交換機(jī),能夠有效保證服務(wù)器托管業(yè)務(wù)安全、可靠、穩(wěn)定、高效運(yùn)行;創(chuàng)新互聯(lián)專注于成都服務(wù)器托管租用十余年,得到成都等地區(qū)行業(yè)客戶的一致認(rèn)可。
網(wǎng)頁標(biāo)題:如何提高數(shù)據(jù)庫join的效率(數(shù)據(jù)庫join效率)
URL鏈接:http://m.fisionsoft.com.cn/article/dphgpii.html


咨詢
建站咨詢
