用过滤器对活动记录对象进行分页的优化方法是什么?



我想用我的rails API在分页中显示Users列表,但是在显示用户之前我有一些约束,我想检查谁有权访问视图文件的用户,下面是代码:

def verified_client
conditions = {}
conditions[:user_name] = fetch_verified_users_with_api_call # returns[user_1,user_2, ....]
@users = User.where(conditions).where('access NOT LIKE ?', 'admin_%').ordered
will_paginate(@users, params[:page])
end

Q1)是否有一种方法,当用户试图获取后续页面(第2页,第3页)时,我不必进行sql调用。n页)?

Q2)当verified_users列表返回百万项时会发生什么?我怀疑SQL会失败

我可以使用查询的限制和偏移量,但我不知道总结果和页面大小来实现相同的,我必须再触发一个SQL调用来获得计数,并编写自己的逻辑来获得页面数。

生成的SQL:

select  *
from  users
where  user_name IN (user_1, user_2 .... user_10000)
AND  (access NOT LIKE 'admin_%')

这个查询很难优化。它可能基本上完成了每个页面的所有工作,并且没有好的方法来防止这种扫描。添加这些可能会有所帮助:

INDEX(access)
INDEX(user, access)

我在in列表中见过70K项,但我没有听说过1M项。发生了什么事?说哪些用户不包括是否更简短?是否存在另一个包含用户列表的表?(有时JOIN比IN工作得更好,特别是如果您已经运行Select来获取列表。)

在构建此查询之前,管理员是否可以从IN列表中过滤出来?然后,

INDEX(user)

可能是非常有益的。

每个用户最多有一行吗?如果是这样,那么可以将分页修改为非常高效。这是通过"记住你离开的地方"来完成的。而不是用OFFSET。更多:http://mysql.rjweb.org/doc.php/pagination

Q1)是否有一种方法,当用户尝试时,我不必进行sql调用获取后续页面(第2页,第3页…)n页)?

分页的整个思想是通过返回记录总数的一个小子集来提高查询速度。在大多数情况下,对第一页的请求数量将大大超过其他页面,所以这很可能是一个过早优化的情况,可能弊大于利。

这实际上是一个问题,最好通过SQL缓存、ETags或其他缓存机制来解决,而不是一次加载一堆页面。

Q2)当verified_users列表返回百万项时会发生什么?我怀疑SQL会失败

您的数据库或应用程序很可能会慢到停止,然后在内存耗尽时崩溃。具体会发生什么取决于你的架构和你的老板在那一天的脾气。

Q1)是否有一种方法,当用户试图获取后续页面(第2页,第3页)时,我不必进行sql调用。n页)?

你可以获得整个结果集并将其存储在你的应用程序中。就数据库而言,这不是慢的或非最佳的。那么性能(包括内存)就是你的应用程序的问题了。

Q2)当verified_users列表返回百万项时会发生什么?我怀疑SQL会失败

将发生的是所有这些条目将被连接到SQL字符串中。可能存在最大SQL字符串大小,一百万个条目会太多。

一个可能的解决方案是,如果你有一种方法来识别数据库中经过验证的用户,并与该表进行连接。

什么是优化的方式来分页活动记录对象与过滤器?

不过早优化数据库的三件事是:(1)使用索引查询而不是表扫描,(2)避免相关子查询,(3)减少网络转数。

确保您有一个它可以使用的索引,特别是对于顺序。所以一定要知道你要的是什么订单。

如果不是以前缀开头的access字段,如果你有一个字段来指示管理员用户,你可以用第一个字段作为管理员字段,第二个字段作为你排序的索引。这允许数据库有效地对记录进行排序,这在使用offsetlimit进行分页时尤其重要。

对于网络转弯,您可能希望使用分页而不用担心网络转弯。一个想法是,如果可能的话,预取下一页。因此,在它得到第1页的结果之后,查询第2页。保存第2页的结果直到被查看,但是当被查看时,得到第3页的结果。

最新更新