2011-04-20 102 views
0

我有軌控制器如下編碼:優化查詢的PostgreSQL-8.4

@checked_contact_ids = @list.contacts.all(
    :conditions => { 
    "contacts_lists.contact_id" => @list.contacts.map(&:id), 
    "contacts_lists.is_checked" => true 
    } 
).map(&:id) 

其等同爲sql

SELECT * 
FROM "contacts" 
INNER JOIN "contacts_lists" ON "contacts".id = "contacts_lists".contact_id 
WHERE ("contacts_lists".list_id = 67494) 

這上面的查詢需要更多的時間來運行,我想另一種方式來運行具有最短時間的相同查詢。

有誰知道請注意我還是有可能的?或者是上面的查詢足以給出輸出結果?

我在等待信息...................

回答

1

我覺得跟你原來的AR查詢中的主要問題是,它沒有做任何聯接完全;你通過@list.contacts從數據庫中抽出一堆對象,然後將大部分工作都扔掉以便獲得ID。

的第一步將是取代"contacts_lists.contact_id" => @list.contacts.map(&:id):joins => 'contact_lists'但你仍然可以拉了一堆東西從數據庫中,實例化一個組對象,然後扔了這一切與.map(&:id)得到公正身份證號碼。

你知道SQL已經所以我可能會直行通過一個便捷方法SQL你的列表模型(或任何@list是),像這樣:

def checked_contact_ids 
    connection.execute(%Q{ 
     SELECT contacts.id 
     FROM contacts 
     INNER JOIN contacts_lists ON contacts.id = contacts_lists.contact_id 
     WHERE contacts_lists.list_id = #{self.id} 
      AND contacts_lists.is_checked = 't' 
    }).map { |r| r['id'] } 
end 

,然後在你的控制器:

@checked_contact_ids = @list.checked_contact_ids 

如果這還不夠快,請檢查contacts_lists表中的索引。

當你確切地知道你需要什麼數據並且你需要它時,沒有理由不直接去SQL;只是將SQL隔離在模型中,並且不應該有任何問題。