2014-06-28 62 views
3

我剛剛從Rails 4.0.2更新到Rails 4.1.2,並意識到ActiveRecord包含的內容變得非常慢。以前只需幾毫秒就可以拍攝近5分鐘。ActiveRecord包含過度連接表在Rails 4.1.2中速度很慢

我在模型中用has_and_belongs_to_many在一個連接表上連接兩個表項和關鍵字。我有近3000個項目,3000個關鍵字和8000個連接表條目。

獲取的所有項目,幷包括曾經是非常快的,但現在,所有關鍵字需要永遠:

Item.includes(:keywords) 

我比較這兩個4.0.2和4.1.2和Rails似乎不使用內部連接的SQL在Rails 4.1.2中再次查詢。數據庫響應時間非常快,所以這不是問題。

SQL爲Rails 4.0.2

項目負載(5.8ms)選擇items。* FROM items

SQL(4.6ms)選擇keywords。*,t0item_id AS ar_association_key_name FROM keywords INNER JOIN items_keywords t0 ON keywordsid = t0keyword_id WHERE t0item_id IN (<ID1> ...)

SQL爲Rails 4.1.2

項目負載(3.7ms)選擇items。* FROM items

HABTM_Keywords負載(2.8ms)SELECT items_keywords。* FROM items_keywords WHERE items_keywordsitem_id IN(<ID1> ...)

關鍵字負荷(0.6ms)選擇keywords。* FROM keywords WHERE keywordsid IN(<ID1> ...)

這是一個已知的問題?我找不到任何關於此的內容,因此我認爲在報告錯誤報告之前最好先問社區。

現在我改變了我的Rails版本回到4.0.2。

謝謝Björn

+0

如果你可以做一個準系統的簡單案例展示這種行爲,那麼我會建議用這個例子提交一份報告。 – pdobb

+0

什麼是爲每個版本的Rails生成的SQL?使用'Item.includes(:keywords).to_sql'來找出。 – infused

+0

我編輯問題幷包含生成的SQL。它已經在4.1.2中改變了,不再使用內部連接,現在執行了三個單獨的查詢。 – dasboe

回答

2

您可以通過顯式引用該協會在這裏避免了性能迴歸:

Item.includes(:keywords).references(:keywords) 

但問題是Rails的範圍內,雖然有一個修復程序,它還沒有發佈,所以我現在把它放在初始化器中。

對我來說,這仍然很慢,但只有大約一半的速度沒有修復。

module ActiveRecord 
    # FIXME: this is a fix pulled from https://github.com/rails/rails/pull/15675 
    # for a serious performance issue, look to remove it on the next Rails upgrade 
    module Associations::Builder 
    class HasAndBelongsToMany 
     def hash 
     object_id.hash 
     end 

     def ==(other) 
     equal?(other) 
     end 
     alias :eql? :== 
    end 
    end 
    module AttributeMethods 
    module PrimaryKey 
     def id 
     return unless self.class.primary_key 
     sync_with_transaction_state 
     read_attribute(self.class.primary_key) 
     end 
    end 
    end 
end