簡體   English   中英

Rails查詢優化(消除n + 1個查詢)

[英]Rails query optimization(eliminating n+1 queries)

我正在一個項目上,有一個復雜的查詢需要花10秒鍾左右的時間來執行。 我意識到有N + 1查詢正在發生,但是我是Rails的新手,我不確定如何解決它。 控制器代碼為:

def index

    filters = params.slice(:package_type, :guid)
    list = packages
    list = list.where(filters) unless filters.empty?

    respond_to do |format|
      format.html { @packages = list.includes(:classification).order(:priority => :asc) }
      format.json { @packages = list.includes(:classification, {channels: [:classification, :genres]}, :extras).order(:priority => :asc) }
    end
  end

包裝型號有

class Package < ActiveRecord::Base
  extend FriendlyId


  belongs_to :classification
  has_many :package_channels
  has_many :channels, -> { order(:priority => :asc, :identifier => :asc) }, through: :package_channels
  has_many :package_extras
  has_many :extras, -> { order(:identifier => :asc) },through: :package_extras

渠道模型具有:

class Channel < ActiveRecord::Base

  belongs_to :classification
  has_many :channel_genres
  has_many :genres, through: :channel_genres
  has_many :package_channels
  has_many :packages, through: :package_channels

我還想提到過濾器通常是空的。 如果我缺少任何信息,請隨時發表評論,我會添加它。 謝謝你的時間!

這是控制器的#packages方法。

 def packages
    @plan ? @plan.packages : Package
  end

這是視圖:index.json.jbuilder

json.cache! ["cache", "#{params["plan_id"]}_packages_index"] do
  json.array! @packages do |package|
    json.partial! 'packages/package_lean', package: package
  end
end

我看不到查詢本身,因此我可能無法專門針對這種情況進行回答。

1.使用急切加載將N + 1個查詢轉換為1個

通常,第一步應該使用預先加載技術來防止N + 1查詢。 您很可能正在請求尚未加載的關聯集合(或單個對象)。

# controller
def index
  @customers = Customer.active
end

# view
<% @customers.each do |c| %>
  <%= c.name %> # this is fine the object is already in memory from your controller
  <%= c.address %> # this one makes a query to the database
<% end %>

這通常可以通過添加includes(association)來解決。

@customers = Customer.active.includes(:address)

2.確保您有關聯的外鍵索引

另一件好事是關聯外鍵的索引。

add_index :customer, :address_id

在為某些復雜的查詢建立執行計划時,數據庫引擎可能會選擇不使用該索引,但是對於一個簡單的查詢,情況就是如此。

3.使用子彈寶石

有一種壞蛋叫做子彈 在開發應用程序時,它將監視您的查詢,並在您應添加緊急加載(N + 1查詢),使用不必要的緊急加載以及何時使用計數器緩存時通知您。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM