我读过ORDER BY RAND()及其性能问题——这些问题只适用于返回大数据集的查询吗?例如,如果我有一个包含100000行的表,并使用WHERE子句返回一个包含10条记录的数据集,然后使用ORDER BY RAND()LIMIT 1,那么在我的表被筛选到与WHERE语句匹配的记录之后,是否会应用此ORDER B Y RAND(),因此性能问题可以忽略不计?
基于快速测试,我必须得出结论,ORDER BY RAND()仅在***WHERE语句应用后***才应用,而不是应用于整个数据集。 50000行表格的结果:
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)
ORDER BY大约是最后一个执行,但LIMIT是最后一次执行。 不幸的是,这意味着DB将为所有符合条件的行生成随机数,对它们排序,然后应用限制。 您可以做的是让表具有代理id字段,生成一个随机数,然后使用 SELECT x,y,z FROM table WHERE id >= your_rand_number
5条答案
按热度按时间s71maibg1#
您是对的,它将在使用WHERE、GROUP BY和HAVING减少行数后应用ORDER BY。但它将在LIMIT之前应用ORDER BY。
因此,如果您充分过滤行数,那么是的,ORDER BY RAND()可以实现您想要的效果,而不会对性能产生很大影响。简单易读的代码有一个合理的好处。
当你认为你的查询应该把行减少到一些小的时候,问题就来了,但是随着时间的推移,你的数据增长,它需要排序的行数又变大了。由于您的查询对排序结果执行LIMIT 10,因此隐藏了您对500k行执行ORDER BY RAND()的事实。你只会看到性能神秘地越来越差。
我在我的书SQL Antipatterns Volume 1: Avoiding the Pitfalls of Database Programming中,或在堆栈溢出的其他答案中,写过关于随机选择行的替代方法:
w51jfk4q2#
无论您选择了多少行。如果
ORDER BY RAND()
,将为表中的每一行计算一个随机数。这是因为它必须计算每一行的随机值,以便知道哪一行生成了最大值。因此,如果您有一个包含100000行的表,然后调用ORDER BY RAND() LIMIT 1
。您正在告诉MySQL为100000行生成一个随机数,按照该数字对它们进行排序,然后给出第一个。执行以下操作要快得多:
1.从
Table
中选择计数()1.在您的脚本/编程语言中生成0和上述查询结果减去1之间的随机数。
1.从
Table
LIMIT random_number_此处选择,1qij5mzcb3#
基于快速测试,我必须得出结论,ORDER BY RAND()仅在***WHERE语句应用后***才应用,而不是应用于整个数据集。
50000行表格的结果:
cvxl0en24#
将为每行计算
RAND()
值,因此对于大型数据集来说,这不是很有效,LIMIT
子句不会改变这一点。解决这个问题的通常方法是预先计算一个随机数,然后根据一些预先生成的索引列检索与之对应的行。下面是一个详细的解释:
http://jan.kneschke.de/projects/mysql/order-by-rand/升
yqlxgs2m5#
ORDER BY
大约是最后一个执行,但LIMIT
是最后一次执行。不幸的是,这意味着DB将为所有符合条件的行生成随机数,对它们排序,然后应用限制。
您可以做的是让表具有代理
id
字段,生成一个随机数,然后使用SELECT x,y,z FROM table WHERE id >= your_rand_number