【问题标题】:Infinite scrolling of shuffled database values无限滚动混洗的数据库值
【发布时间】:2014-05-10 20:46:04
【问题描述】:

我目前有一个无限滚动,当用户到达页面底部时,它会打印数据库行块。

我想做的是打乱整个数据库,以便用户每次加载页面时都以不同的顺序获取它们(但没有条目出现两次)。

这个表只会增长,所以我想尽可能高效地完成它。

我的查询目前是:

mysqli_query($con, "SELECT * FROM shopaholic ORDER BY RAND() LIMIT 36");

这有两个明显的缺点:

  • 很容易重复行,因为它每次都从整个表中挑选行
  • 它正在使用RAND(),所以它会很慢

我该如何以更好的方式解决这个问题?

如果您需要查看其他相关代码,请告诉我。

【问题讨论】:

  • 您正在随机排序。您要么必须创建一个伪随机订单,要么存储在客户端查看过的记录,如果您有很多很多,您可能会遇到客户端减慢或达到本地存储大小限制的问题记录。
  • 我可以接受伪随机 - 我该怎么做?
  • 这是一个组合 P=NP 问题,计算成本可能很高 - 您最好的办法是预先生成一组随机显示,并使其对最终用户显得随机。否则,en.wikipedia.org/wiki/Fisher-Yates_shuffle
  • 伪随机意味着您实际上会事先生成订单,然后从该列表中翻页。

标签: mysql sql random


【解决方案1】:

如果您不打算跟踪用户已经查看了哪些记录,那么他们刷新页面后仍有可能看到相同的记录。

您可以考虑放弃他们看不到任何重复的要求,因为这是最苛刻的要求。也许只是添加一些逻辑,这样他们就不会在同一页面上看到重复项,所以至少不会那么明显。

RAND() 排序将扫描表中的所有行。假设您有一些 auto_increment 主键,您可以在最低和最高主键之间选择一个随机数。你可能会认为1 是最低的,而MAX() 是最高的。

然后进行这样的查询,其中随机值为58494

SELECT * FROM shopaholic WHERE ID >= 58494 LIMIT 1

如果您的主键没有任何空格,您可以使用= 而不是>=

这个查询会很快,因为它只读取一条记录。因此,请在循环中执行此操作(例如,对于 36 条记录的列表执行 36 次)。如果您要跟踪他们看过哪些记录,请对照该数据集检查每条记录,看看他们是否已经看过该记录。您还可以检查该页面是否已加载,这样您至少不会在同一页面上获得重复项。

如果您尝试查找用户尚未查看的记录,当用户翻阅结果时,“随机”查找他们尚未查看的记录将变得越来越昂贵,尤其是在数据集增长。另一个不用担心重复的理由。

【讨论】:

  • 非常感谢。如果它有所作为,我一点也不担心用户在刷新页面时会看到相同的结果。不过,在一次查看中,我想给人一种滚动浏览与它们相关的所有行的感觉,尽管顺序是打乱的。
  • @Sebastian,总共可能有多少条记录?用户可能滚动浏览多少条记录?
  • 一个用户关注多个提要,每个提要包含特定网站上的所有销售项目,因此每个用户很容易有数百条记录。
  • @Sebastian,它真的必须是随机的吗?为什么不按价格、相关性、日期等排序?无论如何,“数百”并不多。如果它必须是随机的,并且没有重复,并且由于数字似乎很小,以至于它们实际上可能会滚动浏览它们,只需使用 ORDER BY RAND() 随机排序列表并将其存储(客户端或服务器端),然后翻阅它们。
  • 我希望它是随机的原因是因为这是一个 Chrome 扩展程序,它将这个提要放在用户的新标签页上,所以我希望每次他们打开新标签页时都能提供新鲜的内容。即使是数千,ORDER BY RAND() 仍然可行吗?
猜你喜欢
  • 2012-01-25
  • 2013-02-22
  • 1970-01-01
  • 1970-01-01
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多