為什么數(shù)據(jù)庫查詢要用小表驅(qū)動(dòng)大表?
在數(shù)據(jù)庫優(yōu)化領(lǐng)域,"小表驅(qū)動(dòng)大表"是一個(gè)常見的最佳實(shí)踐。本文將從原理、場景和實(shí)例三個(gè)維度,通俗解釋這一概念的核心邏輯。
一、什么是"小表驅(qū)動(dòng)大表"?
當(dāng)我們對兩個(gè)表(A表和B表)進(jìn)行JOIN操作時(shí):
- ? 驅(qū)動(dòng)表:外層循環(huán)表(先遍歷的表)
- ? 被驅(qū)動(dòng)表:內(nèi)層循環(huán)表(后匹配的表)
核心原則:讓數(shù)據(jù)量較小的表作為驅(qū)動(dòng)表(外層循環(huán)),數(shù)據(jù)量較大的表作為被驅(qū)動(dòng)表(內(nèi)層循環(huán))。
二、關(guān)鍵區(qū)別:有無索引的不同表現(xiàn)
1. 當(dāng)連接字段沒有索引時(shí)
無論誰做驅(qū)動(dòng)表,本質(zhì)都是全表掃描:
- ? 大表驅(qū)動(dòng)小表:外層循環(huán)100萬次,每次掃描100行 → 總掃描1億次
- ? 小表驅(qū)動(dòng)大表:外層循環(huán)100次,每次掃描100萬行 → 總掃描1億次
結(jié)論:無索引時(shí)效率相同,因?yàn)閽呙璐螖?shù)相同。
2. 當(dāng)連接字段有索引時(shí)(關(guān)鍵場景)
被驅(qū)動(dòng)表的索引會(huì)發(fā)揮關(guān)鍵作用:
- ? 驅(qū)動(dòng)表(小表)每行數(shù)據(jù)作為條件,通過索引快速定位被驅(qū)動(dòng)表(大表)的匹配行
- ? 索引的B+樹結(jié)構(gòu)讓查詢時(shí)間復(fù)雜度降至O(logN),而非全表掃描的O(N)
結(jié)論:小表驅(qū)動(dòng)大表時(shí),內(nèi)層循環(huán)通過索引大幅減少實(shí)際掃描行數(shù),效率顯著提升。
三、實(shí)戰(zhàn)案例:員工表與部門表的JOIN
假設(shè):
- ?
employees
表(大表):100萬條員工記錄,含department_id
字段 - ?
departments
表(小表):100條部門記錄,含id
主鍵
目標(biāo):查詢每個(gè)員工的部門名稱。
1. 錯(cuò)誤示范:大表驅(qū)動(dòng)小表(反模式)
// 外層循環(huán):遍歷100萬條員工記錄
for (Employee e : employees) {
// 內(nèi)層循環(huán):每次都要全表掃描100條部門記錄
for (Department d : departments) {
if (e.departmentId == d.id) {
output(e.name, d.name);
}
}
}
- ? 總比較次數(shù):100萬 × 100 = 1億次
- ? 問題:內(nèi)層循環(huán)無索引,每次都是低效的全表掃描。
2. 正確做法:小表驅(qū)動(dòng)大表(最佳實(shí)踐)
// 外層循環(huán):僅遍歷100條部門記錄
for (Department d : departments) {
// 內(nèi)層循環(huán):通過索引快速查找對應(yīng)員工(關(guān)鍵優(yōu)化點(diǎn))
for (Employee e : employees.findByDepartmentId(d.id)) {
output(e.name, d.name);
}
}
- ? 關(guān)鍵細(xì)節(jié):
employees.findByDepartmentId
使用了索引,每次查詢時(shí)間復(fù)雜度極低 - ? 總操作次數(shù):100次索引查詢 + 實(shí)際匹配的員工數(shù)(遠(yuǎn)小于1億次)
- ? 優(yōu)勢:外層循環(huán)次數(shù)從百萬級降至百級,內(nèi)層通過索引跳過無效數(shù)據(jù)。
四、核心原理總結(jié)
- 1. 索引是前提:小表驅(qū)動(dòng)大表的優(yōu)化效果,必須建立在被驅(qū)動(dòng)表的連接字段有索引的基礎(chǔ)上(通常是外鍵字段加索引)。
- 2. 減少外層循環(huán):小表作為驅(qū)動(dòng)表,直接減少外層循環(huán)次數(shù),這是比內(nèi)層優(yōu)化更重要的成本控制。
- 3. 索引的本質(zhì)優(yōu)勢:通過B+樹結(jié)構(gòu)將數(shù)據(jù)查找從O(N)降至O(logN),尤其適合大表的快速定位。
五、什么時(shí)候會(huì)失效?
如果被驅(qū)動(dòng)表的連接字段沒有索引,或者索引失效(如使用函數(shù)、類型不匹配),小表驅(qū)動(dòng)大表的優(yōu)勢就會(huì)消失。此時(shí)兩種驅(qū)動(dòng)方式效率相同,都需要全表掃描。
六、總結(jié)
"小表驅(qū)動(dòng)大表"的本質(zhì),是通過合理利用索引,將外層循環(huán)的成本控制在最小范圍,同時(shí)讓內(nèi)層循環(huán)通過高效的數(shù)據(jù)查找完成匹配。這一原則在OLTP(在線事務(wù)處理)場景中尤為重要,能顯著提升多表連接的查詢性能。記住:先優(yōu)化外層循環(huán)次數(shù),再依賴索引優(yōu)化內(nèi)層查找。
閱讀原文:原文鏈接
該文章在 2025/5/6 12:40:45 編輯過