代码之家  ›  专栏  ›  技术社区  ›  JP Silvashy Gautam Rege

在需要计数器的轨道中修复N+1查询

  •  1
  • JP Silvashy Gautam Rege  · 技术社区  · 14 年前

    我对优化查询很陌生,我有一个n+1查询,它似乎需要一个计数器,但我不确定如何继续:

    ...
    SQL (0.5ms)  SELECT COUNT(*) AS count_id FROM (SELECT 1 FROM `photos` WHERE (`photos`.attachable_id = 4864 AND `photos`.attachable_type = 'Recipe')) AS subquery
    SQL (2.1ms)  SELECT COUNT(*) AS count_id FROM (SELECT 1 FROM `votes` WHERE (`votes`.voteable_id = 4864 AND `votes`.voteable_type = 'Recipe') AND (`votes`.`vote` = 1)) AS subquery
    SQL (2.0ms)  SELECT COUNT(*) AS count_id FROM (SELECT 1 FROM `votes` WHERE (`votes`.voteable_id = 4864 AND `votes`.voteable_type = 'Recipe') AND (`votes`.`vote` = 0)) AS subquery
    SQL (0.3ms)  SELECT COUNT(*) AS count_id FROM (SELECT 1 FROM `photos` WHERE (`photos`.attachable_id = 4865 AND `photos`.attachable_type = 'Recipe')) AS subquery
    SQL (2.6ms)  SELECT COUNT(*) AS count_id FROM (SELECT 1 FROM `votes` WHERE (`votes`.voteable_id = 4865 AND `votes`.voteable_type = 'Recipe') AND (`votes`.`vote` = 1)) AS subquery
    SQL (2.4ms)  SELECT COUNT(*) AS count_id FROM (SELECT 1 FROM `votes` WHERE (`votes`.voteable_id = 4865 AND `votes`.voteable_type = 'Recipe') AND (`votes`.`vote` = 0)) AS subquery
    ...
    

    所以我有两个奇怪的问题。我有这种多态性 vote 模型,我需要总结一下,基本上,如果有人投了反对票,它的价值是 0 投票 列和A 1 如果用户投了赞成票。不过,它似乎创建了这个疯狂的查询。

    我怎样才能补救?


    我认为造成这种情况的原因从我的观点中的这种方法开始:

    <%= recipe.votes.tally %>
    

    这就是我计算选票的方式:

    class Vote < ActiveRecord::Base
    
      scope :up, where(:vote => true)
      scope :down, where(:vote => false)
    
      def self.tally
        self.up.count - self.down.count
      end
    
    end
    

    但是因为我要为每个对象做很多次,它必须做这个逻辑,我们最终得到一个疯狂的n+1。

    1 回复  |  直到 14 年前
        1
  •  1
  •   Stephan Wehner    14 年前

    当你写作的时候,

    我认为造成这种情况的原因从我的观点中的这种方法开始:

    <%=recipe.votes.tally%>

    通过在脚本/控制台中获取一个配方实例,您可以找到更多的确定性。 执行 配方.投票.计数 那里

    不太确定,这有点含糊,但您是否可以考虑将计数方法放在配方模型中?——Stephan