ORDER BY RAND()替代方案

时间:2009-12-08 16:26:27

标签: mysql performance random

  

可能重复:
  MySQL: Alternatives to ORDER BY RAND()

我目前有一个查询结束ORDER BY RAND(HOUR(NOW())) LIMIT 40以获得40个随机结果。结果列表每小时更改一次。

这会终止查询缓存,这会破坏性能。

您能否建议另一种获取随机(ish)结果集的方法,该方法会不时发生变化?它不必是每个小时,它不必是完全随机的。

我更喜欢随机结果,而不是在表格中的任意字段上排序,但我会这样做作为最后的手段......

(这是我想要随时改变的新产品列表。)

9 个答案:

答案 0 :(得分:6)

如果你有一个ID列,最好做一个:

-- create a variable to hold the random number
SET @rownum := SELECT count(*) FROM table;
SET @row := (SELECT CEIL((rand() * @rownum));

-- use the random number to select on the id column
SELECT * from tablle WHERE id = @row;

选择随机ID号的逻辑可以移到应用程序级别。

SELECT * FROM table ORDER BY RAND LIMIT 40

效率非常低,因为MySQL将处理表中所有行的所有记录,对所有行执行全表扫描,随机排序。

答案 1 :(得分:5)

它会杀死缓存,因为你每次都期望得到不同的结果集。您无法缓存一组随机值。如果要缓存一组结果,请缓存一大组随机值,​​然后在您要使用这些值的子部分内,在较小的集合[sql]之外进行随机抓取。

答案 2 :(得分:3)

我认为更好的方法是将产品标识符下载到中间层,在需要时选择随机的40个值(每小时一次或每个请求一次),并在查询中使用它们:product_id in (@id_1, @id_2, ..., @id_40)

答案 3 :(得分:1)

您可能有一个随机值的列,您每小时都会更新一次。

答案 4 :(得分:1)

如果需要将大型数据集排序为随机顺序(确实需要排序),那么这将是一个非常讨厌的查询,然后丢弃除前40个记录之外的所有数据。

更好的解决方案是选择40个随机记录。有很多方法可以做到这一点,它通常取决于具有均匀分布的键。

另一个选择是在批处理作业中选择40个随机记录,每小时(或其他)只运行一次,然后记住它们是哪些。

答案 5 :(得分:0)

实现它的一种方法是将数据映射到的对象混洗。如果不将数据映射到对象,则可以从数据库中混洗结果数组。我不知道这是否会表现得更好,但是至少你会提到查询缓存带来的好处。

您还可以生成从1到n的随机序列,并使用这些序列索引结果数组(或对象数组)。

答案 6 :(得分:0)

计算PHP代码中的当前小时,并将其传递给您的查询。这将导致可以缓存的静态值。

请注意,您可能还有一个隐藏的错误。因为你只花了一个小时,你只有24个不同的值,每天都会重复。这意味着今天下午1点显示的内容也将与明天6点显示的内容相同。您可能希望更改内容。

答案 7 :(得分:0)

不要与缓存斗争 - 展开它!

按原样编写查询(甚至更简单)。然后,在您的代码中,缓存结果,将缓存过期设置为1小时。如果您正在使用缓存层,例如memcached,则会进行设置。如果没有,你可以构建一个相当简单的:

[pseudocode]
global cache[24]
h = Time.hour
if (cache[h] == null) {
  cache[h] = .. run your query
}
return cache[h];

答案 8 :(得分:0)

如果您每小时只需要一组新的随机数据,请不要点击数据库 - 将结果保存到应用程序的缓存层(或者,如果它没有,请将其暂存到临时某种文件)。查询缓存很方便,但如果你甚至不需要执行查询,那就更好了......