【发布时间】:2011-01-20 22:46:22
【问题描述】:
我正在运行带有 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
]
我的问题是:
- 有人知道为什么会这样吗?为什么使用嵌套的
SELECT查询时双INNER JOIN比我的单INNER JOIN慢? -
find_by_sql调用并没有真正利用 Rails 为 HABTM 关系提供的内置支持。特别是,它显示了 Rails 支持通常从开发人员那里抽象出来的books_users连接表。有没有办法使用隐藏此的find调用来指定相同的查询?
【问题讨论】:
-
您是否为
books_users表的book_id和user_id字段创建了索引? -
Ack... 我知道我忘记了什么。就是这样!添加索引后,查找查询现在需要 15 毫秒。
-
@dmarkow:将其添加为答案,以便我们给您积分
标签: mysql ruby-on-rails