懶加載在訪問關(guān)聯(lián)時(shí)才查詢,易導(dǎo)致N 1問題,適合不確定是否需要關(guān)聯(lián)數(shù)據(jù)的場景;2. 急加載使用with()提前加載關(guān)聯(lián)數(shù)據(jù),避免N 1查詢,適合批量處理場景;3. 應(yīng)優(yōu)先使用急加載優(yōu)化性能,可通過Laravel Debugbar等工具檢測N 1問題,并謹(jǐn)慎使用模型的$with屬性以避免不必要的性能開銷。
在 Laravel 中,懶加載(Lazy Loading) 和 急加載(Eager Loading) 是處理模型關(guān)聯(lián)數(shù)據(jù)的兩種主要方式。它們在性能和使用場景上有明顯區(qū)別,理解它們的區(qū)別對優(yōu)化應(yīng)用性能非常重要。

什么是懶加載(Lazy Loading)
懶加載是指在訪問模型的關(guān)聯(lián)關(guān)系時(shí),才去數(shù)據(jù)庫執(zhí)行查詢加載數(shù)據(jù)。
比如:

$books = Book::all(); foreach ($books as $book) { echo $book->author->name; // 每次訪問 author 都會觸發(fā)一次查詢 }
上面的代碼會先查詢所有書籍(1 次查詢),然后每訪問一本 book
的 author
時(shí),都會單獨(dú)執(zhí)行一次查詢來獲取作者信息。如果有 100 本書,就會額外執(zhí)行 100 次查詢 —— 這就是典型的 N 1 查詢問題。
? 優(yōu)點(diǎn):

- 使用簡單,代碼直觀
- 只在真正需要時(shí)才加載數(shù)據(jù)
? 缺點(diǎn):
- 容易導(dǎo)致 N 1 查詢問題,嚴(yán)重降低性能
- 在循環(huán)中訪問關(guān)聯(lián)數(shù)據(jù)時(shí)特別危險(xiǎn)
什么是急加載(Eager Loading)
急加載是在查詢主模型時(shí),提前把關(guān)聯(lián)數(shù)據(jù)一起加載進(jìn)來,使用 with()
方法。
比如:
$books = Book::with('author')->get(); foreach ($books as $book) { echo $book->author->name; // 數(shù)據(jù)已加載,不再查詢數(shù)據(jù)庫 }
這段代碼只會執(zhí)行 2 次查詢:
- 查詢所有書籍
- 查詢這些書籍對應(yīng)的所有作者(通過一次
IN
查詢)
? 優(yōu)點(diǎn):
- 避免 N 1 問題,大幅提升性能
- 適合批量處理關(guān)聯(lián)數(shù)據(jù)的場景
? 缺點(diǎn):
- 如果關(guān)聯(lián)數(shù)據(jù)量大但實(shí)際用不到,會造成資源浪費(fèi)
- 不能用于動(dòng)態(tài)條件(除非使用約束)
如何選擇:懶加載 vs 急加載?
場景 | 推薦方式 | 說明 |
---|---|---|
循環(huán)中訪問關(guān)聯(lián)數(shù)據(jù) | ? 急加載 | 避免 N 1 查詢 |
只處理少量數(shù)據(jù)或不確定是否需要關(guān)聯(lián) | ? 懶加載 | 簡單直接,避免多余查詢 |
關(guān)聯(lián)數(shù)據(jù)復(fù)雜或數(shù)據(jù)量大 | ?? 謹(jǐn)慎急加載 | 可能導(dǎo)致內(nèi)存占用高 |
需要對關(guān)聯(lián)加條件 | ? with() 閉包 | 支持條件過濾 |
示例:帶條件的急加載
$books = Book::with(['author' => function ($query) { $query->where('active', 1); }])->get();
如何檢測 N 1 問題?
可以使用 Laravel 的調(diào)試工具,如:
- Laravel Debugbar
- Clockwork
- 或者使用
DB::listen()
監(jiān)聽查詢次數(shù)
這些工具能幫你發(fā)現(xiàn)意外的多次查詢。
最佳實(shí)踐建議
- 默認(rèn)優(yōu)先考慮急加載,尤其是在列表頁或 API 返回多個(gè)資源時(shí)
- 使用
with()
預(yù)加載常用關(guān)聯(lián) - 避免在 Blade 模板中訪問未預(yù)加載的關(guān)聯(lián)(容易觸發(fā)懶加載)
- 可通過模型設(shè)置
$with
屬性,自動(dòng)預(yù)加載某些關(guān)聯(lián)(謹(jǐn)慎使用):
class Book extends Model { protected $with = ['author']; // 自動(dòng)預(yù)加載 author }
?? 注意:全局 $with
會影響所有查詢,可能導(dǎo)致不必要的性能開銷。
基本上就這些。簡單說:懶加載方便但容易踩坑,急加載高效但要提前規(guī)劃。在實(shí)際開發(fā)中,應(yīng)盡量避免 N 1 查詢,優(yōu)先使用 with()
來優(yōu)化性能。
以上是Laravel Lazy Loading與急切的加載的詳細(xì)內(nèi)容。更多信息請關(guān)注PHP中文網(wǎng)其他相關(guān)文章!

熱AI工具

Undress AI Tool
免費(fèi)脫衣服圖片

Undresser.AI Undress
人工智能驅(qū)動(dòng)的應(yīng)用程序,用于創(chuàng)建逼真的裸體照片

AI Clothes Remover
用于從照片中去除衣服的在線人工智能工具。

Clothoff.io
AI脫衣機(jī)

Video Face Swap
使用我們完全免費(fèi)的人工智能換臉工具輕松在任何視頻中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費(fèi)的代碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
功能強(qiáng)大的PHP集成開發(fā)環(huán)境

Dreamweaver CS6
視覺化網(wǎng)頁開發(fā)工具

SublimeText3 Mac版
神級代碼編輯軟件(SublimeText3)

usearestapitobridgephpandmlmodelsbyrunningthemodelinpythonviaflaskorfastapiandcallingitfromphpusingcurlorguzzle.2.runpythonscriptsdirectsdirectlyectlyectlyfromphpsingexec()orshell_exec()orshell_exec()orshell_exec()

Laravel支持使用原生SQL查詢,但應(yīng)優(yōu)先使用參數(shù)綁定以確保安全;1.使用DB::select()執(zhí)行帶參數(shù)綁定的SELECT查詢,防止SQL注入;2.使用DB::update()執(zhí)行UPDATE操作并返回影響行數(shù);3.使用DB::insert()插入數(shù)據(jù);4.使用DB::delete()刪除數(shù)據(jù);5.使用DB::statement()執(zhí)行如CREATE、ALTER等無結(jié)果集的SQL語句;6.推薦在QueryBuilder中使用whereRaw、selectRaw等方法結(jié)合原生表達(dá)式以提升安

響應(yīng)式編程在Java中通過ProjectReactor和SpringWebFlux實(shí)現(xiàn)高并發(fā)、低延遲的非阻塞服務(wù)。1.ProjectReactor提供Mono和Flux兩個(gè)核心類型,支持聲明式處理異步數(shù)據(jù)流,并通過操作符鏈進(jìn)行轉(zhuǎn)換、過濾等操作;2.SpringWebFlux基于Reactor構(gòu)建,支持注解式和函數(shù)式兩種編程模型,運(yùn)行在Netty等非阻塞服務(wù)器上,可高效處理大量并發(fā)連接;3.使用WebFlux Reactor能提升I/O密集型場景下的并發(fā)能力與資源利用率,天然支持SSE、WebSo

JWT是一種用于安全傳輸信息的開放標(biāo)準(zhǔn),在Java中可通過JJWT庫實(shí)現(xiàn)認(rèn)證與授權(quán),1.添加JJWT的API、Impl和Jackson依賴;2.創(chuàng)建JwtUtil工具類生成、解析和驗(yàn)證Token;3.編寫JwtFilter攔截請求并校驗(yàn)Authorization頭中的BearerToken;4.在SpringBoot中注冊Filter保護(hù)指定路徑;5.提供登錄接口在驗(yàn)證用戶后返回JWT;6.受保護(hù)接口通過解析Token獲取用戶身份和角色進(jìn)行訪問控制,最終實(shí)現(xiàn)無狀態(tài)、可擴(kuò)展的安全機(jī)制,適合分布式系

Go泛型從1.18開始支持,用于編寫類型安全的通用代碼。1.泛型函數(shù)PrintSlice[Tany](s[]T)可打印任意類型切片,如[]int或[]string。2.通過類型約束Number限制T為int、float等數(shù)字類型,實(shí)現(xiàn)Sum[TNumber](slice[]T)T安全求和。3.泛型結(jié)構(gòu)體typeBox[Tany]struct{ValueT}可封裝任意類型值,配合NewBox[Tany](vT)*Box[T]構(gòu)造函數(shù)使用。4.為Box[T]添加Set(vT)和Get()T方法,無需

table-layout:fixed會強(qiáng)制表格列寬由第一行單元格寬度決定,避免內(nèi)容影響布局。1.設(shè)置table-layout:fixed并指定表格寬度;2.為第一行th/td設(shè)置具體列寬比例;3.配合white-space:nowrap、overflow:hidden和text-overflow:ellipsis控制文本溢出;4.適用于后臺管理、數(shù)據(jù)報(bào)表等需穩(wěn)定布局和高性能渲染的場景,能有效防止布局抖動(dòng)并提升渲染效率。

使用JUnit5和Mockito能有效隔離依賴進(jìn)行單元測試,1.通過@Mock創(chuàng)建模擬對象,@InjectMocks注入被測實(shí)例,@ExtendWith啟用Mockito擴(kuò)展;2.使用when().thenReturn()定義模擬行為,verify()驗(yàn)證方法調(diào)用次數(shù)與參數(shù);3.可模擬異常場景并驗(yàn)證錯(cuò)誤處理;4.推薦構(gòu)造函數(shù)注入、避免過度模擬、保持測試原子性;5.使用assertAll()合并斷言,@Nested組織測試場景,從而提升測試可維護(hù)性和可靠性。

Choosetheappropriateindextypebasedonusecase,suchassinglefield,compound,multikey,text,geospatial,orTTLindexes.2.ApplytheESRrulewhencreatingcompoundindexesbyorderingfieldsasequality,sort,thenrange.3.Designindexestosupportcoveredqueriesbyincludingallque
