【发布时间】:2012-05-07 21:07:52
【问题描述】:
假设您有三个模型:
class Collection < ActiveRecord::Base
has_many :comments, through => :users
end
class User < ActiveRecord::Base
belongs_to :collection
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :user
end
这样的索引:
add_index :users, :collection_id
add_index :comments, :user_id
如果您有其 cmets 的集合查询:
@collection.comments
它会使用两个索引吗?
编辑:
这会产生一个如下所示的查询:
SELECT "comments".* FROM "comments" INNER JOIN "users" ON "comments"."user_id" = "users"."id" WHERE "users"."collection_id" = 232
使用 EXPLAIN 它声称它仅使用“对用户使用 index_users_on_collection_id 进行索引扫描”
所以大概它从用户的collection_id索引中快速获取用户,然后在加入用户时搜索所有的cmets?如果有很多 cmets(假设有 100,000 个),这个查询会不会执行得不好?
谢谢。
【问题讨论】:
-
与其对
EXPLAIN的输出进行模糊的描述,为什么不显示呢?更好的是,显示EXPLAIN ANALYZE输出,这样我们就可以看到预期 行数和成本以及实际 行数和时间。此外,不要期望大型数据集上的计划与小型数据集上的计划相同。 -
执行计划不是假设性的,它们是根据当前基数和过滤器和连接字段的选择性的估计来制定的。如果您认为使用 100K cmets 的计划会很慢,那么只有当您生成具有 100K cmets 和当前统计数据的计划时才有意义。如果您遇到实际性能问题,请按照@kgrittn 的建议运行并发布
explain analyze。 -
通常评论来自一个用户。所以你的数据模型可能不符合要求。可能应该是 n:1 而不是 n:m - 一个表
comment,其外键列引用作者 (user)。 -
在开发、暂存等任何情况下使用 Rails 插入 100,000 条记录(或更多数量级)并再次运行解释非常容易。
标签: ruby-on-rails ruby-on-rails-3 activerecord postgresql-9.1 rails-postgresql