2011-04-20 70 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隔离在模型中,并且不应该有任何问题。