什么是“改组”数据库记录表的最佳方法?

时间:2011-01-05 23:37:07

标签: mysql ruby-on-rails database random

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

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

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

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

替代解决方案可能是创建另一列来排序记录,随机每次插入时间单位。这里的问题是,我需要将序列中的随机数设置为表中的每个记录,这将占用与记录一样多的查询。

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

3 个答案:

答案 0 :(得分:7)

试试这个:

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)。另请注意,如果重复最后三个查询,则每次都会得到相同的结果。

答案 1 :(得分:2)

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

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

答案 2 :(得分:2)

如果随机结果是“为每个人”而不是任何特定用户,那么你可以这样做:(这适用于Postgres,应该与其他人合作)

update mytable set sortorder = random() * 100000000;

select * from mytable order by sortorder, primarykeyid;

由于随机MAY可以重复,因此通过primarykeyid进行的二次排序可以使排序具有一定的稳定性。

然后,您可以根据需要刷新缓存来执行此操作。例如,给你的页面绝对过期,比方说,每分钟。然后每分钟重新更新排序顺序并正常提供页面。

如果您在刷新窗口中收到请求,那么,是的,您有可能让不同的页面获得相同的结果。你也会遇到问题,当他们“回来”时,他们可能无法获得他们之前的页面(自刷新以来)。

归结为随机数据的呈现背后的动机是什么,这将是多么有效。它还取决于数据量等。

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