讓 Laravel Scout 導入提速 64 倍

文章轉發自專業的Laravel開發者社區,原始連接:learnku.com/laravel/t/2…laravel

下一個版本的 Laravel Scout 將會使你的模型查詢速度提高64倍。git

我使用null scout 驅動測試了一張包含 1,632,576條數據的表。消耗的時間從過去的29分57秒縮短到了28秒。 [1]^github

你能在這裏 查看提交的 pull request.數據庫

這篇文章解釋了爲何代碼中的這個更改會帶來這麼大的變化。這是我在我本身的 Laravel 應用中用來加速存在問題的查詢的一個技巧。一旦你理解了它的原理,我打賭你會找到一種新的優化你的應用的方式。bash

背景

默認狀況下, Scout 會檢索數據庫中的每一行。爲了保持內存使用的合理性,它使用 chunk 方法 一次只取幾百行。post

chunk 方法爲你的查詢添加了限制和偏移量,像這樣:測試

select * from `users` order by `id` asc limit 500 offset 500;
複製代碼

要獲取下一頁,偏移量會遞增。優化

select * from `users` order by `id` asc limit 500 offset 1000;
複製代碼

首先這很好用,這個查詢大約只須要大約一毫秒,但你走的越遠,它就越慢。ui

一旦偏移量達到了 1,000,000 ,查詢速度就會很容易慢 500 倍。當 Scout 導入執行數千個這樣的查詢時,它會累加起來。spa

爲何偏移量速度慢

當你使用偏移量時,你是在告訴數據庫要跳過前 N 行。即便沒有返回跳過的這些行,數據庫仍然會從磁盤讀取它們並對它們進行排序。

數據庫 可能 可以使用索引並避免獲取整個行。咱們的示例查詢中使用主鍵索引,但仍然能夠抓取。

使 ChunkById 更快的分塊

事實證實,不使用偏移量就能夠很容易地對結果進行分頁。咱們所要作的就是跟蹤咱們看到的最後一個 ID ,而後過濾結果,以便只獲取咱們未見到的行。若是結果是按 ID 升序排序的,咱們可使用一個簡單的 WHERE ID > :last_id 子句進行篩選。查詢語句最終就會是像這樣:

select * from `users` where `id` > :last_id order by `id` asc limit 500;
複製代碼

使用這種技術後,加載最後一頁和第一頁加載速度是同樣快。

Laravel 讓這絕不費力。不要調用 chunk 而是調用 chunkById 方法(在 5.2 中添加)。查詢構造器將會添加 where 語句、 order by 和 limit 。

API 與 chunk 徹底相同。只要你不使用任何自定義的 order by 子句,它就是 4 個字符的變化。


  1. 返回原文 ↩︎

相關文章
相關標籤/搜索