使用过滤器对 Active Record 对象进行分页的优化方法是什么?
What is the Optimized way to Paginate Active Record Objects with Filter?
我想用我的 rails API 分页显示用户列表,但是在显示用户之前我在这里几乎没有限制我想检查有权访问视图文件的用户,这是代码:
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 页...第 n 页)时,有没有一种方法可以让我不必进行 sql 调用?
Q2) 当 verified_users 列出 return 百万物品时会发生什么?我怀疑 SQL 会失败
我本可以在查询中使用限制和偏移量,但我不知道要实现相同的总结果和页面大小我必须再触发一次 SQL 调用来获取计数并自己编写获取页数的逻辑。
生成SQL:
select *
from users
where user_name IN (user_1, user_2 .... user_10000)
AND (access NOT LIKE 'admin_%')
Q1) Is there a way where I don't have to make sql call when users try
to fetch subsequent pages(page 2, page 3.. page n)?
分页的整个思想是通过返回记录总数的一小部分来加快查询速度。在大多数情况下,第一页的请求数量将远远超过其他页面,因此这很可能是过早优化的情况,可能弊大于利。
如果这确实是一个问题,那么使用 SQL 缓存、ETag 或其他缓存机制更好地解决问题 - 而不是一次加载一堆页面。
Q2) What would happen when verified_users list return million on items? I suspect the SQL will fail
您的数据库或应用程序很可能会变慢而停止,然后在内存不足时崩溃。具体会发生什么取决于您的架构以及您的老板在那一天的脾气暴躁程度。
该查询很难优化。它可能基本上完成了每个页面的所有工作,并且没有好的方法来阻止这种扫描。添加这些可能会有所帮助:
INDEX(access)
INDEX(user, access)
我见过一个IN列表有70K条,没听说过1M。到底是怎么回事?说哪些用户 不 会更短吗?用户列表可以有另一个 table 吗? (有时 JOIN
比 IN 效果更好,特别是如果您已经 运行 一个 Select 来获取列表。)
在构建此查询之前是否可以将管理员从 IN 列表中过滤掉?那么,
INDEX(user)
可能会非常有益。
每个用户最多一行吗?如果是这样,则可以将分页修改为 非常 高效。这是通过“记住你离开的地方”而不是使用 OFFSET
来完成的。更多:http://mysql.rjweb.org/doc.php/pagination
Q1) Is there a way where I don't have to make sql call when users try to fetch subsequent pages(page 2, page 3.. page n)?
您可以获得整个结果集并将其存储在您的应用程序中。就数据库而言,这并不慢或不是最佳的。那么包括内存在内的性能就是您应用的问题。
Q2) What would happen when verified_users list return million on items? I suspect the SQL will fail
将会发生的是所有这些条目都将连接到 SQL 字符串中。可能存在最大 SQL 字符串大小,一百万个条目太多了。
一个可能的解决方案是,如果您有办法识别数据库中经过验证的用户并与该用户进行连接 table。
What is the Optimized way to Paginate Active Record Objects with Filter?
不对数据库进行过早优化的三件事是 (1) 使用索引查询而不是 table 扫描,(2) 避免相关子查询,以及 (3) 减少网络转向。
确保您有一个它可以使用的索引,尤其是订单。因此,请确保您知道自己要求的顺序。
如果您有一个字段表示管理员用户,而不是 access
字段以前缀开头,您可以创建一个索引,其中第一个字段作为该管理员字段,第二个字段作为您的身份订购。这允许数据库有效地对记录进行排序,在使用 offset
和 limit
.
进行分页时尤其重要
至于网络轮流,您可能希望使用寻呼而不用担心网络轮流。一个想法是如果可能的话预取下一页。所以它得到第1页的结果后,查询第2页。保持第2页的结果直到查看,但是当查看时,然后获取第3页的结果。
我想用我的 rails API 分页显示用户列表,但是在显示用户之前我在这里几乎没有限制我想检查有权访问视图文件的用户,这是代码:
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 页...第 n 页)时,有没有一种方法可以让我不必进行 sql 调用?
Q2) 当 verified_users 列出 return 百万物品时会发生什么?我怀疑 SQL 会失败
我本可以在查询中使用限制和偏移量,但我不知道要实现相同的总结果和页面大小我必须再触发一次 SQL 调用来获取计数并自己编写获取页数的逻辑。
生成SQL:
select *
from users
where user_name IN (user_1, user_2 .... user_10000)
AND (access NOT LIKE 'admin_%')
Q1) Is there a way where I don't have to make sql call when users try to fetch subsequent pages(page 2, page 3.. page n)?
分页的整个思想是通过返回记录总数的一小部分来加快查询速度。在大多数情况下,第一页的请求数量将远远超过其他页面,因此这很可能是过早优化的情况,可能弊大于利。
如果这确实是一个问题,那么使用 SQL 缓存、ETag 或其他缓存机制更好地解决问题 - 而不是一次加载一堆页面。
Q2) What would happen when verified_users list return million on items? I suspect the SQL will fail
您的数据库或应用程序很可能会变慢而停止,然后在内存不足时崩溃。具体会发生什么取决于您的架构以及您的老板在那一天的脾气暴躁程度。
该查询很难优化。它可能基本上完成了每个页面的所有工作,并且没有好的方法来阻止这种扫描。添加这些可能会有所帮助:
INDEX(access)
INDEX(user, access)
我见过一个IN列表有70K条,没听说过1M。到底是怎么回事?说哪些用户 不 会更短吗?用户列表可以有另一个 table 吗? (有时 JOIN
比 IN 效果更好,特别是如果您已经 运行 一个 Select 来获取列表。)
在构建此查询之前是否可以将管理员从 IN 列表中过滤掉?那么,
INDEX(user)
可能会非常有益。
每个用户最多一行吗?如果是这样,则可以将分页修改为 非常 高效。这是通过“记住你离开的地方”而不是使用 OFFSET
来完成的。更多:http://mysql.rjweb.org/doc.php/pagination
Q1) Is there a way where I don't have to make sql call when users try to fetch subsequent pages(page 2, page 3.. page n)?
您可以获得整个结果集并将其存储在您的应用程序中。就数据库而言,这并不慢或不是最佳的。那么包括内存在内的性能就是您应用的问题。
Q2) What would happen when verified_users list return million on items? I suspect the SQL will fail
将会发生的是所有这些条目都将连接到 SQL 字符串中。可能存在最大 SQL 字符串大小,一百万个条目太多了。
一个可能的解决方案是,如果您有办法识别数据库中经过验证的用户并与该用户进行连接 table。
What is the Optimized way to Paginate Active Record Objects with Filter?
不对数据库进行过早优化的三件事是 (1) 使用索引查询而不是 table 扫描,(2) 避免相关子查询,以及 (3) 减少网络转向。
确保您有一个它可以使用的索引,尤其是订单。因此,请确保您知道自己要求的顺序。
如果您有一个字段表示管理员用户,而不是 access
字段以前缀开头,您可以创建一个索引,其中第一个字段作为该管理员字段,第二个字段作为您的身份订购。这允许数据库有效地对记录进行排序,在使用 offset
和 limit
.
至于网络轮流,您可能希望使用寻呼而不用担心网络轮流。一个想法是如果可能的话预取下一页。所以它得到第1页的结果后,查询第2页。保持第2页的结果直到查看,但是当查看时,然后获取第3页的结果。