所以我有一个执行此操作的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
,where
,update_all
是否与使用纯SQL相同。目前它效率不高,因为我在声明中填写了大量WineClubMembership
条记录。
有更有效的方法吗?虽然这是一个长期丑陋的陈述,但我认为它在大多数情况下都是有效的,因为它在数据库的一两次点击中完成所有操作。但是,我周围的人都在想,必须有其他“Rails方法”能够以更好的方式做到这一点,不会影响生产网站的性能。
我确实看到过“批量”搜索,但我不确定这是否会有所帮助。
更新
我正在使用Postgres 9.1+。在我的activerecord搜索的旧版本(稍微简单一点)中,这就是出现的内容:
Ruby代码:
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, ...)))
答案 0 :(得分:0)
如果您的数据库管理最终NOT IN比较的源代码,可能会在数据库中进行优化以便处理它。让sql管理id列表,而不是传递300,000项长数组。如果您的数据库允许尝试类似
的内容... NOT IN (SELECT billing_info_id FROM wine_club_memberships)").update_all("card_number = ''")
就Rails特定的加速速度的方法而言,除了将纯sql字符串传递给dbs之外,你通常不会做得更好(性能方面,如果不是可维护性)。 / p>