在使用 laravel 開發(fā)包含大量數(shù)據(jù)的應(yīng)用時,分頁是一個常見的需求。然而,當數(shù)據(jù)量達到數(shù)十萬甚至數(shù)百萬級別時,傳統(tǒng)的 paginate() 方法由于其底層的 offset 和 limit 實現(xiàn)方式,可能會導(dǎo)致查詢速度急劇下降,嚴重影響用戶體驗。
我之前就遇到了類似的問題。一個包含大量用戶數(shù)據(jù)的管理后臺,在進行分頁查詢時,響應(yīng)時間竟然高達幾十秒,這簡直無法接受。經(jīng)過一番研究,我發(fā)現(xiàn)了 aaronfrancis/fast-paginate 這個 laravel 包,它通過一種稱為“延遲連接”(deferred join)的 sql 技術(shù),極大地優(yōu)化了分頁查詢的性能。
composer在線學(xué)習(xí)地址:學(xué)習(xí)地址
延遲連接的原理
fast-paginate 的核心思想是延遲對數(shù)據(jù)的訪問,直到應(yīng)用了 offset 和 limit 之后。它通過創(chuàng)建一個子查詢,該子查詢僅獲取需要分頁的 ID,然后再使用這些 ID 從主表中檢索完整的行數(shù)據(jù)。
用 SQL 語句來表示,大概是這樣的:
select * from contacts -- 你想要展示給用戶的完整數(shù)據(jù) where contacts.id in ( -- "延遲連接" 或子查詢 select id from contacts -- 分頁,只訪問盡可能少的數(shù)據(jù) - 僅 ID limit 15 offset 150000 )
然而,由于 mysql 的限制,fast-paginate 實際上會將這個查詢拆分成兩個獨立的查詢來執(zhí)行,以避免 LIMIT & IN/ALL/ANY/SOME subquery 錯誤。
安裝與使用
安裝 fast-paginate 非常簡單,只需通過 Composer 引入即可:
composer require aaronfrancis/fast-paginate
安裝完成后,就可以直接在任何使用 Model::query()->paginate() 的地方,替換為 Model::query()->fastPaginate(),方法簽名完全相同,無需修改其他代碼。
例如:
use AppModelsUser; $users = User::query()->fastPaginate(15); // 每頁顯示 15 個用戶
甚至可以用于關(guān)聯(lián)關(guān)系的分頁:
$posts = User::first()->posts()->fastPaginate(10); // 獲取第一個用戶的 10 篇文章
實際效果
在使用 fast-paginate 后,我的管理后臺分頁查詢速度得到了顯著提升。原本需要幾十秒的查詢,現(xiàn)在只需要幾百毫秒,用戶體驗得到了極大的改善。
根據(jù)社區(qū)反饋,fast-paginate 的性能提升非常明顯:
- 30 秒 –> 250 毫秒
- 28 秒 –> 2 秒
- 7.5 倍加速
- 1.1 秒 –> 0.1 秒
- 20 秒 –> 2 秒
- 2 秒 –> 0.2 秒
總結(jié)
aaronfrancis/fast-paginate 是一個簡單而強大的 Laravel 包,可以有效解決大數(shù)據(jù)量下的分頁慢查詢問題。它通過延遲連接的 SQL 技術(shù),優(yōu)化了查詢性能,提升了用戶體驗。如果你正在 Laravel 項目中遇到分頁性能瓶頸,不妨嘗試一下 fast-paginate,相信它會給你帶來驚喜。