我们有一个包含50k项目的表格,我们会在搜索页面上显示一个随机排序,每页10个项目。我们需要应用一些过滤器。
带或不带种子的 RAND()
非常慢。请注意,项目有三个类别。第一个类别应首先显示随机顺序,然后是第二个类别,也是随机顺序。
有没有更好的解决方案来加速这种随机搜索?
答案 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
值列表可能是非随机顺序。