iT邦幫忙

2023 iThome 鐵人賽

DAY 24
0
Software Development

Zero to Ruby on Rails系列 第 24

Day 24 - Rails N + 1 問題

  • 分享至 

  • xImage
  •  

什麼是 N + 1 問題?

N + 1 問題是當需要從資料庫中找資料時,應該要一次抓完所需資料,但卻使用逐筆撈資料的方式處理,可能會導致大量的資料庫查詢,這種情況通常在 Rails 中的 Active Record 查詢中出現,尤其是大量使用關聯性時,白話來說在同一個地方本來可以一次抓例如5個資料,卻分成5次慢慢抓這樣

N + 1 問題 EX:

# 在 controller 中 抓所有文章及其評論
@posts = Post.all

# 在 view 中跑過所有文章並輸出評論數
<% @posts.each do |post| %>
  <p><%= post.title %></p>
  <p>評論數:<%= post.comments.count %></p>
<% end %>

上述程式碼中,我們首先抓取了所有文章,然後在 view 中遍歷每篇文章以顯示評論數。但是,每次調用 post.comments.count 都會觸發一個額外的資料庫查詢,這就造成了 N + 1 問題,因為我們執行了 N 次(文章數量)的附加查詢

解決 N + 1 問題的方法

使用 includes 或 eager_load

includes 和 eager_load 方法,可以在查詢主模型時先預載關聯模型的資料,而減少額外的查詢

# 使用 includes 預加載關聯模型的評論數據
@posts = Post.includes(:comments)

# 或者使用 eager_load
@posts = Post.eager_load(:comments)

使用 joins

使用 joins 方法來聯接主模型和關聯模型,然後通過 select 方法選擇所需的字串,減少不必要的數據擷取

@posts = Post.joins(:comments).select('posts.*, COUNT(comments.id) AS comments_count').group('posts.id')

手動緩存資料

手動緩存某些數據,以減少重複查詢

@posts = Post.all
@comment_counts = Comment.group(:post_id).count

使用 gem 套件

有一些 gem 套件(例如 bullet 和 rack-mini-profiler)可以幫忙檢測並解決 N + 1 問題,以幫助優化查詢

結論

N + 1 問題是在 Ruby on Rails 開發中常見的性能問題,但可以通過使用內建方法和技巧來解決。選擇所需的方法,並根據專案的複雜性和數據量來優化查詢,了解和解決 N + 1 問題是開發高效率 Rails 應用程式的重要技巧

預告

明天預計來介紹什麼是 gem ,我們明天見!


上一篇
Day 23 - Model 關聯性
下一篇
Day 25 - Gem 套件
系列文
Zero to Ruby on Rails30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言