快速rand()订单搜索

时间:2014-11-19 12:42:23

标签: mysql performance random random-sample

我们有一个包含50k项目的表格,我们会在搜索页面上显示一个随机排序,每页10个项目。我们需要应用一些过滤器。

带或不带种子的

RAND()非常慢。请注意,项目有三个类别。第一个类别应首先显示随机顺序,然后是第二个类别,也是随机顺序。

  • 生成0到max_id之间的随机数,因为页面和前面提到的约束
  • 而无效
  • 使用php随机化记录使项目始终显示在同一页面

有没有更好的解决方案来加速这种随机搜索?

2 个答案:

答案 0 :(得分:0)

这里有一些小费希望它可以运作

  • 将索引放在要过滤的主域上
  • 减少选择查询中的列数(仅使用所需列)
  • 重新检查你的联接
  • 重新检查你的条件
  • 重新检查您的小组/拥有/订购条款

答案 1 :(得分:0)

提示:除非您尝试使用可重现的项目序列进行测试,否则不要为RAND()调用播种。

如果没有大量的编程,这几乎是完美的。与此同时,这里有几件事要做。

首先,试试这个。而不是SELECT * FROM t ORDER BY RAND() LIMIT 10使用以下类型的子查询:

SELECT * FROM t
 WHERE id IN (
   SELECT id FROM t WHERE category = 1 ORDER BY RAND() LIMIT 10
   UNION ALL
   SELECT id FROM t WHERE category = 2 ORDER BY RAND() LIMIT 10
  )
ORDER BY RAND()

这应该可以节省ORDER BY RAND() LIMIT 10操作的时间,因为它只需要调整id值,而不是整个记录。但这不是算法的变化,只是数据量的变化:它仍然需要改变整个id值列表。所以这是一个快速补丁,而不是一个真正的修复。

其次,如果您可以编写一个PHP函数来生成一个文本字符串,比如1和max_id之间的100个随机数,您可以尝试这个来获得第一个类别。

 SELECT * FROM t WHERE id IN
     ( SELECT DISTINCT id FROM t 
        WHERE category = 1 AND id IN (num, num, num, ..., num, num)
        LIMIT 10 )
 ORDER BY RAND()

这将在指定类别中为您提供十个或更少的随机选择的记录,非常便宜。请注意,您必须在(num, num, num, num)列表中提供十个以上的随机数,因为并非所有num值对category = 1行都有效。

如果您需要多个类别,只需在UNION中使用类似的查询即可获得其他类别。

(category, id)上的复合索引将改善这些方法的表现。

请注意,在每个方法查询的末尾都有一个额外的ORDER BY RAND()。那是因为子查询生成的id值列表可能是非随机顺序。