PostgreSQL ActiveRecord查询优化
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PostgreSQL ActiveRecord查询优化相关的知识,希望对你有一定的参考价值。
我是RoR的新手,我需要一个返回与以下队列定义相同的实例的查询:
@all = User.all
@membersOfActivity = User.where(id: User.joins(:memberships).where("activity_id = ?", session[:current_activity_id]))
@usersIAlreadyLiked = User.where(id: User.joins(:likes).where("activity_id = ? AND activity_likes_user IS NOT NULL", session[:current_activity_id]))
@notWanted = @membersOfActivity + @usersIAlreadyLiked
@queue = @all - @notWanted
但是,我理解我刚写的查询是多么低效,因为它首先下载所有用户然后选择补充。您是否知道如何提高效率并直接选择@notWanted的补充?我尝试了几个查询,但没有一个有效。如果您认为自己有更好的解决方案,请告诉我们!谢谢!
编辑:每个用户都有许多成员资格,用于将用户与活动联系起来。所以每项活动也有很多会员资格。每个成员资格都有一个user_id和一个activity_id。
每个用户都有很多喜欢,每个用户都喜欢连接用户和活动。因此每项活动也有很多喜欢。类似具有user_id,activity_id,user_liked_activity和activity_liked_user。
如果用户没有表达对活动的意见,则user_liked_activity为NULL,如果用户喜欢该活动,则为TRUE,如果用户不喜欢该活动,则为FALSE。 Viceversa for activity_liked_user。
这是一个使用not
语法的Rails 5解决方案。乍一看,这似乎与您的原始解决方案类似,但这只运行一个查询,从单独的排他性类别(members
和already_liked
)构建。
class User < ApplicationRecord
has_many :likes
has_many :memberships
def self.queue(current_activity_id)
members = User.joins(:memberships).where(memberships: {activity_id: current_activity_id})
already_liked = User.joins(:likes).where(likes: {activity_id: current_activity_id, activity_liked_user: [true, false]})
where.not(id: members).where.not(id: already_liked)
end
end
您将从控制器中调用此方法,如下所示:
@queue = User.queue(session[:current_activity_id])
据我所知,对于当前的会话活动,我们需要一个查询,它将返回除属于两个类别之一的所有用户:(1)作为活动成员的用户,由具有成员关联链接的用户表示当前活动,以及(2)已经从活动中获得“喜欢”评级的用户,由具有“like”的用户表示,该用户与当前活动相关联,其中activity_likes_user为true或false(但不是nil)。
我们为每个类别建立ActiveRecord关系,但我们不会调用实际触发查询的任何内容。第1类是members
,第2类是already_liked
。
现在我们在User
模型上建立一个查询(这是隐含的,因为我们在User
类的类方法中调用)要求用户id不是members
之一而不是already_liked
之一。
可能有更优雅的解决方案,但这确实有效,我相信它可以正确处理边缘情况,但您应该构建测试来验证这一点。
以上是关于PostgreSQL ActiveRecord查询优化的主要内容,如果未能解决你的问题,请参考以下文章