【问题标题】:Speed up a rails database query using postgresql使用 postgresql 加速 Rails 数据库查询
【发布时间】:2021-06-28 13:39:18
【问题描述】:

我正在尝试加快 Rails 查询的速度,但我重新加载页面会耗费大量时间。

我在 rails 视图中有这个:

<% if current_account.subscribed? and current_account.subscription.plan.id == 2 %>  
  <div class="flex items-center bg-blue-100 rounded-lg px-2 mb-2 shadow-lg data-controller="tooltip" data-tippy-content="Clases reservadas este mes" data-tippy-delay="0" data-tippy-arrow="true" data-tippy-size="regular" data-tippy-animation="fade">
    <div class="mr-2 flex-shrink-0 text-3xl md:text-2xl">
      ????
    </div>
    <div>
      <p class="text-3xl md:text-2xl font-bold">
        <%= @lessons_basic_count %>
      </p>
    </div>
  </div>

这是我在控制器上运行的查询:

@lessons_basic_count = @mylessons_lessons.where(datetime: Time.at((current_account.subscription.latest_payment.created if current_account.subscription.latest_payment).to_i)..(Date.current + 30.days)).size

这是一个查询表mylessons,其中包含用户在实际订阅期间预订的课程。

谢谢。

【问题讨论】:

  • 生成的SQL是什么?如果你进入 PostgreSQL 控制台并输入 EXPLAIN &lt;SQL here&gt; 它会显示什么?也许您需要此表上的一列或一组列的索引。
  • EXPLAIN for: SELECT "lessons".* FROM "lessons" INNER JOIN "mylessons" ON "lessons"."id" = "mylessons"."lesson_id" WHERE "mylessons"."user_id" = $1 AND "lessons"."datetime" BETWEEN $2 AND $3 [["user_id", 18], ["datetime", "2021-06-28 12:50:20"], ["datetime", "2021-07-28"]] QUERY PLAN这是最后没有.size的SQL查询
  • 你是如何定义latest_payment的?顾名思义,订阅has_many :payments。如果您通过加载所有付款而不是使用查询来确定最新付款,则可能会大大减慢速度。

标签: ruby-on-rails ruby performance activerecord


【解决方案1】:

EXPLAIN 输出中QUERY PLAN 之后的信息很重要。您能否在问题中包含该输出?

看起来您可能希望在 mylessons 表上为 user_id 和 datetime 设置双键。您可以在迁移中添加以下内容:

add_index :mylessons, [:user_id, :datetime]

您还需要mylessons.lesson_id 的索引。可以添加如下内容:

add_index :mylessons, :lesson_id

【讨论】:

  • 查询计划后我得到了这个Hash Join (cost=46.76..127.95 rows=8 width=506) Hash Cond: (mylessons.lesson_id = lessons.id) -&gt; Seq Scan on mylessons (cost=0.00..81.13 rows=109 width=4) Filter: (user_id = 955) -&gt; Hash (cost=46.54..46.54 rows=65 width=506) -&gt; Seq Scan on lessons (cost=0.00..46.54 rows=65 width=506) Filter: ((datetime &gt;= '2021-06-19 09:26:54'::timestamp without time zone) AND (datetime &lt;= '2021-07-28 00:00:00'::timestamp without time zone)) (7 rows)
  • 看起来您还需要在mylessons.lesson_id 上建立索引。您的解释计划没有使用任何索引条件。当它说Seq Scan 时,这意味着它必须扫描整个表。您的查询正在扫描您的mylessons 表和lessons 表。
猜你喜欢
  • 2015-01-25
  • 2015-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-30
  • 2018-04-21
  • 1970-01-01
相关资源
最近更新 更多