【问题标题】:What's the best way to "shuffle" a table of database records?“打乱”数据库记录表的最佳方法是什么?
【发布时间】:2011-06-04 08:48:20
【问题描述】:

假设我有一个包含一堆记录的表,我想随机呈现给用户。我还希望用户能够来回分页,所以我必须保持某种顺序,至少在一段时间内。

该应用程序基本上只有 AJAX,它对已经访问过的页面使用缓存,所以即使我总是提供随机结果,当用户尝试返回时,他会得到上一个页面,因为它将从本地缓存加载.

问题是,如果我只返回随机结果,可能会有一些重复。每个页面包含 6 个结果,因此为了防止这种情况,我必须执行类似 WHERE id NOT IN (1,2,3,4 ...) 之类的操作,我将在其中放置所有以前加载的 ID。

该解决方案的巨大缺点是无法在服务器端缓存任何内容,因为每个用户都会请求不同的数据。

另一种解决方案可能是创建另一列来对记录进行排序,并随机播放每个在此处插入时间单位。这里的问题是,我需要为表中的每条记录设置一个序列中的随机数,这将需要与记录一样多的查询。

如果有任何相关性,我正在使用 Rails 和 MySQL。

【问题讨论】:

  • 作为用户对随机数据进行分页对我来说没有多大意义。如果您将其称为“另外 6 个随机帖子!”并且只是忍受可能的重复,这似乎主要是你所要求的零额外努力。
  • 那么对答案的回应如何?我很想知道建议的任何解决方案是否适合您。

标签: mysql ruby-on-rails database random


【解决方案1】:

试试这个:

mysql> create table t (i int);
mysql> insert into t values (1),(2),(3),(4),(5),(6);
mysql> select * from t order by rand(123) limit 2 offset 0;
+------+
| i    |
+------+
|    6 | 
|    4 | 
+------+
mysql> select * from t order by rand(123) limit 2 offset 2;
+------+
| i    |
+------+
|    2 | 
|    3 | 
+------+
mysql> select * from t order by rand(123) limit 2 offset 4;
+------+
| i    |
+------+
|    5 | 
|    1 | 
+------+

请注意,rand() 函数有一个种子值 (123)。另请注意,如果您重复最后三个查询,每次都会得到相同的结果。

【讨论】:

  • ORDER BY RAND() 是最糟糕的,因为它需要 mySQL 复制整个表,将 RAND() 值添加到每一行,最后进行排序。在 6 行表上没有问题,但在更多行时效率非常低。预计您的 mySQL 服务器会变得更慢和过载。
【解决方案2】:

如果随机结果是“针对所有人”而不是任何特定用户,那么您可以执行以下操作:(这是针对 Postgres,应该与其他人一起使用)

update mytable set sortorder = random() * 100000000;

select * from mytable order by sortorder, primarykeyid;

由于 random MAY 重复,primarykeyid 的二次排序使排序具有一定的稳定性。

然后,您可以根据需要随时刷新缓存。例如,给你的页面一个绝对过期时间,比如说,每分钟。然后每分钟更新排序顺序并正常提供页面。

如果您通过刷新窗口收到请求,那么,是的,您有可能让不同的页面获得相同的结果。您还会遇到这样的问题:当他们点击“返回”时,他们很可能无法获得之前的页面(因为它已刷新)。

可以归结为展示随机数据背后的动机是什么,以及它的效果如何。它还取决于数据量等。

但如果这对您很重要,这是一种缓存友好的方式来实现这一点。它也是无状态的(不需要会话信息)。

【讨论】:

    【解决方案3】:

    我会执行以下操作(假设是顺序的数字主键):

    1. 生成一个随机数并将其存储在用户的会话中
    2. 当用户翻阅数据时,查询总行数
    3. 使用存储在会话中的数字作为种子,在每个请求上生成相同的“随机”ID 顺序
    4. 翻阅 id 并仅从数据库中检索与这些 id 匹配的记录。

    【讨论】:

      猜你喜欢
      • 2011-09-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多