对Sinatra app的N + 1查询

时间:2014-05-30 12:56:06

标签: ruby sinatra rails-activerecord

所以我在我的控制台上收到了这三个查询:

D, [2014-05-30T09:41:15.504655 #4629] DEBUG -- :    (0.2ms)  SELECT COUNT(*) FROM "posts"  WHERE ("posts"."published_on" IS NOT NULL)
D, [2014-05-30T09:41:15.506857 #4629] DEBUG -- :   Post Load (0.3ms)  SELECT  "posts".* FROM "posts"  WHERE ("posts"."published_on" IS NOT NULL)  ORDER BY published_on DESC LIMIT 1 OFFSET 0
D, [2014-05-30T09:41:15.513479 #4629] DEBUG -- :    (0.3ms)  SELECT COUNT(count_column) FROM (SELECT  1 AS count_column FROM "posts"  WHERE ("posts"."published_on" IS NOT NULL) LIMIT 1 OFFSET 0) subquery_for_count

我确实谷歌这个并发现了这个'N + 1个问题'而且很多但不是真正的答案为什么;所以我不知道我是否应该解决这个问题,或者如何(我是Ruby / sinatra的新手)

在我的代码上我所做的就是:

count = Post.where.not({published_on: nil}).count
....
@posts = Post.where.not({published_on: nil}).order("published_on DESC").limit(per_page).offset(offset)

在中间我做一些计算,使用count来计算偏移量,然后在@ post.length之后知道我是否得到任何结果。

我的模型非常简单,Post(w / has_many标签),Tag和PostTags都可以关联它们。

如果必须,有任何改变这个的提示吗?

由于

1 个答案:

答案 0 :(得分:0)

N + 1问题与ORM中您想要获取项目子项的查询相关,并且发现ORM逐个查询它们(请参阅What is SELECT N+1?)。

你的问题似乎与此无关。我已将您的问题追溯到此code(日志中的提示为subquery_for_count):

def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
  # Postgresql doesn't like ORDER BY when there are no GROUP BY
  relation = unscope(:order)
  ...
  if operation == "count" && (relation.limit_value || relation.offset_value)
    # Shortcut when limit is zero.
    return 0 if relation.limit_value == 0

    query_builder = build_count_subquery(relation, column_name, distinct)
    bind_values = query_builder.bind_values + relation.bind_values
  else
  ...

...

def build_count_subquery(relation, column_name, distinct)
  column_alias = Arel.sql('count_column')
  subquery_alias = Arel.sql('subquery_for_count')

这意味着如果您将countlimitoffset混合,则关系计算模块将添加额外查询...