4

我有一个看起来像这样的自定义查询

self.account.websites.find(:all,:joins => [:group_websites => {:group => :users}],:conditions=>["users.id =?",self])

其中 self 是一个用户对象

我设法 为相同的生成等效的SQL

这里看起来如何

sql = "select * from websites INNER JOIN group_websites on group_websites.website_id = websites.id INNER JOIN groups on groups.id = group_websites.group_id INNER JOIN group_users ON (groups.id = group_users.group_id) INNER JOIN users on (users.id = group_users.user_id) where (websites.account_id = #{account_id} AND (users.id = #{user_id}))"

有了对SQL 和 ActiveRecord的良好理解,我假设(大多数人都同意) 从上述查询获得的结果可能比从 find_by_sql(sql) one 获得的结果需要更长的时间

但出人意料

当我运行上述两个时,我发现 ActiveRecord 自定义查询在加载时间方面领先于 ActiveRecord“find_by_sql” 这里是测试结果

ActiveRecord 自定义查询加载时间

网站负载(0.9ms)

网站栏目(1.0ms)

find_by_sql 加载时间

网站负载(1.3ms)

网站栏目(1.0ms)

我再次重复测试,结果仍然相同(自定义查询赢得了战斗)

我知道差异并没有那么大,但我仍然无法弄清楚为什么普通的 find_by_sql 查询比自定义查询慢

任何人都可以分享这一点。

不管怎么说,还是要谢谢你

问候维伦·内吉

4

2 回答 2

1

使用 find 情况,查询是参数化的;这意味着数据库可以缓存查询计划,不需要再次解析和编译查询。

对于 find_by_sql 情况,整个查询作为字符串传递给数据库。这意味着数据库无法对查询的结构进行缓存,并且每次都需要对其进行解析和编译。

我认为您可以对此进行测试:以这种方式尝试 find_by_sql (参数化):

User.find_by_sql(["select * from websites INNER JOIN group_websites on group_websites.website_id = websites.id INNER JOIN groups on groups.id = group_websites.group_id INNER JOIN group_users ON (groups.id = group_users.group_id) INNER JOIN users on (users.id = group_users.user_id) where (websites.account_id = ? AND (users.id = ?))", account_id, users.id])
于 2011-02-22T12:38:03.490 回答
0

好吧,原因可能很简单——使用自定义 SQL,SQL 查询会立即发送到数据库服务器执行。请记住,Ruby 是一种解释型语言,因此 Rails 会根据您使用的 ORM 元语言生成一个新的 SQL 查询,然后才能将其发送到实际的数据库服务器执行。我想说额外的 0.1 毫秒是框架生成查询所花费的时间。

于 2011-02-22T11:56:54.723 回答