OOZOU
與我們聯繫
返回 TIL 列表
ruby on rails

Postgres 函式與 Non-sargable 查詢

October 13, 2020

在 where 子句中使用 postgres 函式可能會讓查詢變成 non-sargable。

資料庫結構

tracks has_many artists

Non-Sargable 查詢

使用 LOWER 函式會讓 DBMS 引擎無法使用索引。

Track.joins(:artists).where('LOWER(tracks.display_name) LIKE ?', "eric clapton%").explain

Gather  (cost=1000.85..56714.32 width=4061)
   Workers Planned: 2
   ->  Nested Loop  (cost=0.85..55713.62 rows=3 width=4061)
         ->  Nested Loop  (cost=0.42..55708.37 rows=3 width=4069)
               ->  Parallel Seq Scan on tracks  (cost=0.00..55365.17 rows=41 width=4061)
                     Filter: (lower((display_name)::text) ~~* 'eric clapton%'::text)
               ->  Index Scan using index_artist_relations_on_artist_item_type_and_artist_item_id on artist_relations  (cost=0.42..8.36 rows=1 width=16)
                     Index Cond: (((artist_item_type)::text = 'Track'::text) AND (artist_item_id = tracks.id))
         ->  Index Only Scan using idx_35952_primary on artists  (cost=0.43..1.75 rows=1 width=8)
               Index Cond: (id = artist_relations.artist_id)

Sargable 查詢

移除 LOWER 函式後,DBMS 引擎就能使用索引,執行速度也更快。

Track.joins(:artists).where('tracks.display_name ILIKE ?', "eric clapton%").explain

Nested Loop  (cost=1497.60..2695.43 width=4061)
   ->  Nested Loop  (cost=1497.17..2684.94 rows=6 width=4069)
         ->  Bitmap Heap Scan on tracks  (cost=1496.75..1873.05 rows=97 width=4061)
               Recheck Cond: ((display_name)::text ~~* 'eric clapton%'::text)
               ->  Bitmap Index Scan on index_tracks_on_display_name  (cost=0.00..1496.73 rows=97 width=0)
                     Index Cond: ((display_name)::text ~~* 'eric clapton%'::text)
         ->  Index Scan using index_artist_relations_on_artist_item_type_and_artist_item_id on artist_relations  (cost=0.42..8.36 rows=1 width=16)
               Index Cond: (((artist_item_type)::text = 'Track'::text) AND (artist_item_id = tracks.id))
   ->  Index Only Scan using idx_35952_primary on artists  (cost=0.43..1.75 rows=1 width=8)
         Index Cond: (id = artist_relations.artist_id)

Sargable 與 Non-Sargable

Sargable 查詢是指可以利用索引來加速的查詢。Sargable 查詢讓 DBMS 引擎能執行 index seek,比掃描整張資料表快得多。Non-sargable 查詢無法使用索引,所以比較慢。「sargable」一詞來自「Search ARGument ABLE」,意思是 DBMS 引擎可以利用索引來最佳化查詢。理解 sargable 與 non-sargable 的差異,是最佳化資料庫的關鍵。

Non-Sargable 查詢

Non-sargable 查詢可能對查詢效能造成很大影響,在大型資料集上尤其明顯。當查詢是 non-sargable 時,DBMS 引擎必須進行 full table scan 或 index scan,兩者都是很重的操作。這可能導致執行時間變慢、CPU 使用率升高,以及整體系統效能不佳。找出並最佳化 non-sargable 查詢,是改善資料庫效率與回應速度的關鍵。

WHERE 子句中的函式

在 WHERE 子句中使用函式可能會讓查詢變成 non-sargable。這是因為當函式套用在 WHERE 子句中的欄位上時,DBMS 引擎無法利用索引來最佳化查詢。舉例來說,考慮查詢 SELECT FROM table WHERE UPPER(column) = 'VALUE'。這是 non-sargable 的,因為 UPPER 函式套用在欄位上,導致索引無法使用。要讓這個查詢變成 sargable,可以移除函式並把查詢改寫為 SELECT FROM table WHERE column = 'VALUE'。這樣 DBMS 引擎就能使用索引,查詢也會更快。

索引與查詢最佳化

索引是查詢最佳化的關鍵,因為它讓 DBMS 引擎能快速找到資料,進而加速查詢。但只有在查詢是 sargable 時才能使用索引。如果查詢是 non-sargable,索引就派不上用場,查詢也會變慢。所以請在 WHERE 子句用到的欄位上建立索引,並確保查詢是 sargable。這會大幅提升資料庫的效能。

轉換 Non-Sargable 述詞

把 non-sargable 述詞轉換為 sargable 是查詢最佳化的一個步驟。透過改寫查詢,移除任何妨礙索引使用的函式或運算,就能把 non-sargable 述詞轉換為 sargable。例如查詢 SELECT FROM table WHERE YEAR(date) = 2022 是 non-sargable 的,因為 YEAR 函式套用在 date 欄位上。要讓這個查詢變成 sargable,你可以把它改寫為 SELECT FROM table WHERE date >= '2022-01-01' AND date < '2023-01-01'。改寫後的查詢是 sargable 的,因為 DBMS 引擎可以利用 date 欄位上的索引來最佳化查詢,速度也會更快。

更多關於 ruby on rails 的筆記

ruby on railsFebruary 10, 2022

用 Pundit Policy 管理 permitted parameters、預設值與各 action 的參數

要管理 permitted params,你可以在你的 policy 中加入 permitted\attributes 和 permitted\attributes\for\#{action},例如

ruby on railsJanuary 31, 2022

在 Turbo 中用 `requestSubmit` 送出表單

Turbo 會監聽 form 上的 submit 事件。因此,用 JS 送出表單時,請一律使用 requestSubmit。

ruby on railsJanuary 19, 2022

在 GitHub Actions 中讓 Rubocop 與 ESLint 忽略 bundled gems

Rails 專案在 GitHub actions 中通常會把 gems 安裝到 vendor 目錄,方便在後續執行時使用快取。

有專案構想嗎?

我們很樂意聆聽您正在打造的產品。

開始對話hello@oozou.com
OOZOU Logo

曼谷 · 新加坡 · 香港

X
Facebook
Instagram
LinkedIn

服務

  • Web 開發
  • AI 代理人與生成式 AI
  • 行動應用開發
  • 數據分析與工程
  • UI/UX 與產品設計
  • 數位轉型

公司

  • 關於我們
  • 職涯
  • 部落格
  • 案例研究
  • Today I Learned
  • 聯繫我們

更多

  • 產業
  • 合作夥伴網絡
© 2026 OOZOU. 版權所有。
隱私政策行為準則反賄賂反貪腐政策