我正在使用MySQL数据库运行Rails 2.3.5。我在Books
和Users
之间有一个HABTM关系,并且我试图让所有拥有指定书籍列表的用户(由一系列图书名称定义)。
我可以执行find
调用来检索此用户列表:
User.find(
:all,
:joins => :books,
:conditions => { :books => { :name => book_names } }
)
然而,事实证明这是非常缓慢的。在SQL中玩游戏后,我发现以下调用的速度更快,并检索相同的结果:
User.find_by_sql([
"SELECT users.* FROM users
INNER JOIN books_users ON users.id = books_users.user_id
WHERE books_users.book_id IN (SELECT id FROM books WHERE books.name IN (?))",
book_names
])
对于同一个查询,find
调用在我的计算机上大约需要3000毫秒,而find_by_sql
调用大约需要200毫秒;这是一个完整的速度差异。我怀疑罪魁祸首与原始find
调用被转换为双INNER JOIN
SQL查询这一事实有关,相当于以下内容:
[
"SELECT users.* FROM users
INNER JOIN books_users ON users.id = books_users.user_id
INNER JOIN books ON books_users.book_id = books.id
WHERE books.name IN (?)",
book_names
]
我的问题是:
INNER JOIN
比我的单INNER JOIN
慢,并且嵌套SELECT
查询?find_by_sql
调用并未真正利用Rails为HABTM关系提供的内置支持。特别是,它正在显示Rails支持的books_users
连接表通常从开发人员那里抽象出来。有没有办法使用隐藏此内容的find
调用来指定相同的查询?答案 0 :(得分:1)
在上述评论之后,您似乎需要book_id
中user_id
和books_users
字段的索引。
class AddIndices < ActiveRecord::Migration
def self.up
add_index :books_users, :book_id
add_index :books_users, :user_id
end
def self.down
remove_index :books_users, :book_id
remove_index :books_users, :user_id
end
end
答案 1 :(得分:0)
使用:include vs.:join更好地加入?
User.find(
:all,
:include => :books,
:conditions => { :books => { :name => book_names } }
)