我已经阅读了ORDER BY RAND()及其性能问题 - 这些仅适用于返回大型数据集的查询吗?例如,如果我有一个包含100,000行的表并使用WHERE子句返回包含10条记录的数据集,然后使用ORDER BY RAND()LIMIT 1,那么在我的表被过滤到表后,将应用此ORDER BY RAND()记录匹配WHERE子句,因此性能问题可以忽略不计?
答案 0 :(得分:8)
你是对的,它会在减少WHERE,GROUP BY和HAVING的行数后应用ORDER BY。但它会在LIMIT之前应用ORDER BY。
因此,如果您充分过滤掉行数,那么是的,ORDER BY RAND()可以达到您想要的效果而不会对性能产生很大影响。对于简单易读的代码,有一个合理的好处。
当您认为您的查询应该将行减少到一些小的时候会出现问题,但随着数据的增长,随着时间的推移,它需要排序的行数会再次变大。由于您的查询然后对排序结果执行了LIMIT 10,因此隐藏了您在500k行上执行ORDER BY RAND()的事实。你只是看到性能神秘地变得更糟。
我已经写过关于在我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming中选择随机行的替代方法,或者在Stack Overflow上的其他答案:
答案 1 :(得分:2)
您选择的行数无关紧要。如果ORDER BY RAND()
,则为表中的每一行计算一个随机数。这是因为它必须计算每一行的随机值,以便知道哪一行产生了最大值。因此,如果您有一个包含100,000行的表,然后调用ORDER BY RAND() LIMIT 1
您告诉MySQL生成100,000行的随机数,按该数字排序,然后给您第一个。
要快得多:
SELECT COUNT(*)FROM Table
在脚本/编程语言中,在0和上述查询结果减1之间生成随机数。
SELECT * FROM Table
LIMIT random_number_here,1
答案 2 :(得分:1)
基于快速测试,我必须得出结论,ORDER BY RAND()仅在 应用WHERE语句后应用 ,而不应用于整个数据集。
包含50,000行的表的结果:
SELECT * FROM `mytable` LIMIT 1 (1 total, Query took 0.0007 sec)
SELECT * FROM `mytable` WHERE First = 'Hilda' LIMIT 1 (1 total, Query took 0.0010 sec)
SELECT * FROM `mytable` WHERE First = 'Hilda' (142 total, Query took 0.0201 sec)
SELECT * FROM `mytable` WHERE First = 'Hilda' ORDER BY RAND() LIMIT 1 (1 total, Query took 0.0229 sec)
SELECT * FROM `mytable` WHERE First = 'Hilda' ORDER BY RAND() (142 total, Query took 0.0236 sec)
SELECT * FROM `mytable` ORDER BY RAND() LIMIT 1 (1 total, Query took 0.4224 sec)
答案 3 :(得分:0)
将为每一行计算RAND()
值,因此对于大型数据集来说效率不高,LIMIT
子句不会改变它。解决此问题的常用方法是提前计算随机数,然后根据某些预生成的索引列检索与其对应的行。
以下是一个详细解释: