MySQL ORDER BY RAND()函数何时命令?

时间:2011-08-02 10:26:48

标签: mysql performance random

我已经阅读了ORDER BY RAND()及其性能问题 - 这些仅适用于返回大型数据集的查询吗?例如,如果我有一个包含100,000行的表并使用WHERE子句返回包含10条记录的数据集,然后使用ORDER BY RAND()LIMIT 1,那么在我的表被过滤到表后,将应用此ORDER BY RAND()记录匹配WHERE子句,因此性能问题可以忽略不计?

4 个答案:

答案 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行的随机数,按该数字排序,然后给您第一个。

要快得多:

  1. SELECT COUNT(*)FROM Table

  2. 在脚本/编程语言中,在0和上述查询结果减1之间生成随机数。

  3. 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子句不会改变它。解决此问题的常用方法是提前计算随机数,然后根据某些预生成的索引列检索与其对应的行。

以下是一个详细解释:

http://jan.kneschke.de/projects/mysql/order-by-rand/