2011-08-02 65 views
2

我已经RAND()和它的性能问题,阅读有关订单 - 做这些只适用于返回大数据集的查询?举例来说,如果我有10万行的表,并且使用WHERE子句返回10条记录的数据集,然后使用ORDER BY RAND()LIMIT 1,经过我的表已经渗透到将这个ORDER BY RAND()被应用记录匹配WHERE子句,因此具有可忽略的性能问题?MySQL ORDER BY RAND()函数何时排序?

+0

几乎任何东西可以很快去的时候只能用小数据集进行操作,但在概念上一个LIMIT ORDER BY子句后适用。所以它取决于查询优化器。为什么不试试一个测试数据库? –

+0

请参阅下面的实验 - 将ORDER BY RAND()应用于WHERE子句返回的记录的子集 - 对于返回143条记录的记录集,限制为随机记录的时间可以忽略不计,而应用它对整个表没有where子句花费了更多的时间。 – key2starz

回答

8

你说得对,它会与WHERE,GROUP BY减少的行数和HAVING后应用ORDER BY。但它会在LIMIT之前应用ORDER BY。

因此,如果您筛选的行数下降充分,那么,在ORDER BY RAND()可以达到你想要的东西没有一个伟大的业绩影响。代码的合法利益很简单,易于阅读。

当您的认为您的查询应该将行数减少到某个较小值时,就会出现问题,但随着数据量的增长,需要排序的行数再次变大。由于您的查询,则不会对排序结果LIMIT 10隐藏,你BY RAND()上的50万行执行订单的事实。你只是看到神秘的表现越来越糟。

我已经写了有关替代方法在我的书SQL Antipatterns: Avoiding the Pitfalls of Database Programming,或在这里其他的答案对堆栈溢出选择一个随机行:

+0

另外两张海报与您的答案相矛盾,并表示无论WHERE子句如何,它都会为表格中的所有行生成随机数字;根据我自己的测试,你的答案是正确的答案。谢谢!在我的情况下,我需要一个来自数据库表的一小部分的随机行。 – key2starz

+0

条例草案,如果你阅读这个,我读了关于你的2查询技术在这里:http://stackoverflow.com/questions/3558665/randomizing-large-dataset/3558919#3558919在我的情况下,我需要使用多个查询加入等等。这种技术在这种情况下也能起作用吗? – key2starz

0

RAND()值将针对每一行进行计算,因此对于大型数据集不是非常有效,LIMIT子句不会更改该值。要解决这个通常的方法是计算提前一个随机数,然后检索基于一些预生成索引列与之对应的行。

这里有一个详细的解释:

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

2

不要紧,你有多少行选择。如果ORDER BY RAND()为表中的每一行计算一个随机数。这是因为它必须计算每一行的随机值才能知道哪一行产生了最大的值。所以,如果你有10万行的表,然后调用ORDER BY RAND() LIMIT 1你告诉MySQL来产生一个随机数为100,000行,由数排序,然后给你的第一个。

这是很要快得多:从Table

    1. SELECT COUNT(*)生成的脚本/编程语言0和上面的查询结果减去1之间的随机数。

    2. SELECT * FROM Table LIMIT random_number_here,1

  • 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)