1

所以我有一个执行此操作的 rake 任务:

  wine_club_memberships = WineClubMembership.pluck(:billing_info_id)
  total_updated = BillingInfo.joins(:order).where(["orders.ordered_date < (CURRENT_DATE - 90) AND billing_infos.card_number IS NOT NULL AND billing_infos.card_number != '' AND billing_infos.id NOT IN (?)", wine_club_memberships]).update_all("card_number = ''")
  log.error("Total records updated #{total_updated}")

问题是 BillingInfo 有 300,000 多条记录joins,我想知道这一切是否与使用纯 SQL 相同。目前它的效率不是很高,因为我在语句中填充了大量的记录。whereupdate_allWineClubMembership

有没有更有效的方法来做到这一点?尽管这是一个长而丑陋的陈述,但我认为它在大多数情况下会很有效,因为它几乎只需一两次访问数据库即可完成所有工作。但是,我周围的人认为必须有其他“Rails 方法”可以以更好的方式做到这一点,而不会影响生产网站的性能。

我确实看到“批量”进行搜索,但我不确定这是否会有所帮助。

更新

我正在使用 Postgres 9.1+。在我的 activerecord 搜索的旧(稍微简单一点)版本中,结果如下:

红宝石代码:

  wine_club_memberships = WineClubMembership.pluck(:billing_info_id)
  total_updated = BillingInfo.joins(:order).where(["orders.ordered_date < (CURRENT_DATE - 90) AND billing_infos.id NOT IN (?)", wine_club_memberships]).update_all("card_number = ''")

生成的 SQL:

  SQL (127848.6ms)  UPDATE "billing_infos" SET card_number = '' WHERE "billing_infos"."id" IN (SELECT "billing_infos"."id" FROM "billing_infos" INNER JOIN "orders" ON "orders"."id" = "billing_infos"."order_id" WHERE (orders.ordered_date < (CURRENT_DATE - 90) AND billing_infos.id NOT IN (423908,390663,387323,402393,383446,416114,391009,456371,384305,386681,384382,384418, ...)))
4

1 回答 1

0

如果您让您的数据库管理最终 NOT IN 比较的源,则可能会在数据库中进行优化以处理它,即让 sql 管理 id 列表而不是传递一个 300,000 项长的数组。如果您的数据库允许尝试类似

... NOT IN (SELECT billing_info_id FROM wine_club_memberships)").update_all("card_number = ''")

至于加速这一过程的特定于 Rails 的方法,您通常不会比仅将纯 sql 字符串传递给 dbs 做得更好(性能方面,如果不是可维护性方面的话)。

于 2013-06-14T21:48:54.757 回答