Categories: Uncategorized

優化 Laravel 中的大型 whereIn 查詢緩慢問題

Laravel Eloquent whereIn() 每個人都用過,但你曉得但 whereIn() 量大時,可能會造成查詢緩慢問題之一嗎? 他不一定是資料 index 索引的問題,可能是更底層問題喔
這邊提供一個 Laravel 資料庫查詢效能優化的手式

Laravel 查詢緩慢的情境

常有的需求是使用指定的 id 取出多個使用者 (e.g. my_table.users.id)

一般透過 eloquent 可能會這樣做 (這邊先不考慮分頁問題)

User::whereIn('id', [1,2,3,4....... x100])->get()

而實際上 Eloquent 會轉換為 SQL statement,如下~

SELECT * FROM users WHERE id in (?, ?, ?, ?, ?, ......)

但查詢對象達到一定數量之後,會發現資料庫回應速度變慢!

查詢緩慢的問題原因

這是因為 Eloquent QueryBuilder 在綁定查詢參數時造成的,他不是 Laravel 的問題而是 PHP Data Objects (PDO) 一個古老的 Bug,PDO 在進行參數綁定時緩慢造成的 (可以想象他要依序綁上上百萬的參數…)

Laravel. 5.7 之後可以改用 whereIntegerInRaw() 替換 whereIn()
就如字面上的意思 (raw) 會直接將參數置入 sql 內,省去 PDO bindings 上參數的動作

替換後的查詢語法為:

User::whereIntegerInRaw('id', [1,2,3,4....... x100])->get()

實際的 SQL statement,如下~

SELECT * FROM users WHERE id in (1, 2, 3, 4, 5, ......)

實際上測試如下

簡單重現,使用 range(1, 50000) 執行 whereIn(),前三次花費時間為 2.4x 秒

後三次改用 whereIntegerInRaw() 進行查詢,可以看見大幅降低所需時間至 0.2~0.3 秒


使用限制

當然這麼好的功能當然有些限制要注意

  • 參數只能是 integers
  • 要注意 SQL injection
可樂

Recent Posts

Simpany 是如何進行、改善 Performance Review (績效考核)

Performance Review 也稱績效考核或年度自我評量 引用至 WIki 譯自英文-績效考核、績效評估,有時縮寫為“ PA”,是一個定期,系統的過程,通過此過程可以記錄和評估員工的工作績效。這是在員工接受工作培訓並安頓下來之後進行的。績效評估是職業發展的一部分,包括對組織內部員工績效的定期審核。績效評估通常由員工的直屬主管進行。wiki: https://en.wikipedia.org/wiki/Performance_appraisal Performance Review 關係到薪資、升遷和薪水習習相關! 你怎麼能不重視呢~ 一般公司的 Review 大概是,主管搜集…

2 days ago

plain PHP 搭配 Slack 進行錯誤追蹤、回報(Error Tracking、Error Handling)

錯誤追蹤、回報非常重要,看到的錯誤才知道怎麼修。現今 PHP 流行的 Laravel 有很好的 Error Tracking, Error Handling。但 plain PHP 怎麼辦呢? 在 production 為了安全考量會設定…

4 years ago

Drone CI/CD 配合 Github 使用 Rsync 進行 Deploy

jenkins、circleci、travis 或 Gitlab CI 皆為目前暫知名的 CI/CD 服務,各自缺點也不言而喻...過於肥大、收費略高(?)、速度不夠快執問題...此時使用 go language 開發的 Drone 就出現啦,完全 docker 容器化的運行方式讓整個 CI…

4 years ago

Nginx brotli 設定

網頁壓縮技術中 gzip 很好用,deflate 己經過時,但你聽過 brotli 嗎? 有著比 gzip 更好、更快的壓縮效率。看起來利大於弊有什麼不用他的理由嗎?簡單從優、缺點來看 brotli!到底 brotli 布羅特利是什麼、如何設定呢。 目前大多的 web server…

4 years ago

本機使用 Docker 容器內 PHP (wrapper/expose PHP)

為什麼要讓本機使用 Docker 內 PHP? 情境... docker 容器內用的是 PHP 7.4 但你的開發本機還在跑 PHP 5.6 或是更舊,因為 dockerize 的關係會將所有相關環境都轉移到…

4 years ago

為什麼你需要密碼管理工具

為什麼你需要密碼管理工具現代人一天下來需要輸入多少組密碼,工作與生活己經和密碼密不可分! 除了足夠全安的密碼,密碼記錄、儲存的方式又足夠安全嗎?密碼管理工具可以帶來什麼幫助呢? 為什麼你需要密碼管理工具 資安問題!!大多人說著沒做壞事不怕被偷資料、監聽。嚴重曝露出現代人的基本科技素養的低落和無知 🤯 密碼的使用無所不在!! 行動裝置的普及,APP 、手機遊戲、銀行帳戶所有和生活相關的東西都需要密碼!!facebook, line 只要打開 APP 也會輸入密碼只是他是自動輸入、一般情況不可視 (auth token) 一般人最常發生的密碼資安問題…

4 years ago