为什么Ruby on Rails执行`SELECT 1 AS one`查询?

问题描述 投票:2回答:1

我目前正在使用Ruby on Rails进入一个项目,我实际上没有任何经验。现在,我们遇到了一些我认为与执行太多查询有关的性能问题。

我们在控制器中设置了Service模型,如下所示:

@services = Service.includes(:points).with_points

with_points范围在服务中定义如下:

scope :with_points, -> { joins(:points).where.not(points: []).distinct }

(我认为这里不需要where子句,但这可能与问题无关。)

然后在视图中,我们使用带有链接点的获取服务,如下所示:

<% @services.each do |s| %>
    <div class="col-xs-12 col-sm-6 col-lg-4 serviceDiv" data-rating="<%= s.service_ratings %>" >
        <% if s.service_ratings == "A" %>
            <% grade = "rating-a" %>
                <!-- etc. -->

现在,就我周围的研究而言,当尝试列出表中的所有行时,这是一个相对正常的模式。但是,当我查看日志时,看起来每个服务都执行单独的查询?

# This query is what I'd expect:
SQL (1.6ms)  SELECT DISTINCT "services"."id" # etc, etc
# But then we also get one of these for every service
Service Exists (1.5ms)  SELECT  1 AS one FROM "services" WHERE "services"."name" = $1 AND ("services"."id" != $2) LIMIT $3
# And quite a few of these for every service:
CACHE Service Exists (0.0ms)  SELECT  1 AS one FROM "services" WHERE "services"."name" = $1 AND ("services"."id" != $2) LIMIT $3

现在,我的预感是那些“服务存在”线是坏消息。它们是什么,它们来自哪里?我还缺少其他与此相关的内容吗?

ruby-on-rails
1个回答
1
投票

在@ MarekLipka关于这个问题的评论中指出之后,我设法找到了问题的根源。不确定将来会有多少人遇到此设置,但我会分享以防万一。

我们访问s.service_ratings的线索是,实际上这不是数据库中的一列。 ActiveRecord Query Trace指出所有这些查询的来源是视图中对s.service_ratings的引用,这是一个红旗。

service_ratings实际上是一个方法(假设我在这里使用了正确的术语)在Service模型上,除了基于对几个模型属性的计算返回值之外,还称为self.update_attributes以实际将该值存储在数据库中。这意味着每次我们检索此模型的数据以显示它时,我们还会运行另一个查询以将该值保存到数据库中 - 通常是冗余的。

换句话说,我们现在的解决方案是在其他某个时间点运行计算并将其存储在数据库中一次,或者在我们每次需要时重新计算它并且根本不存储它。

© www.soinside.com 2019 - 2024. All rights reserved.