MySQL ORDER BY RAND()函数何时排序?

xpcnnkqh  于 2022-10-22  发布在  Mysql
关注(0)|答案(5)|浏览(207)

我读过ORDER BY RAND()及其性能问题——这些问题只适用于返回大数据集的查询吗?例如,如果我有一个包含100000行的表,并使用WHERE子句返回一个包含10条记录的数据集,然后使用ORDER BY RAND()LIMIT 1,那么在我的表被筛选到与WHERE语句匹配的记录之后,是否会应用此ORDER B Y RAND(),因此性能问题可以忽略不计?

s71maibg

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中,或在堆栈溢出的其他答案中,写过关于随机选择行的替代方法:

  • 使用MySQL选择随机行
  • 随机化大数据集
  • 在mysql中从大表中快速选择随机行
w51jfk4q

w51jfk4q2#

无论您选择了多少行。如果ORDER BY RAND(),将为表中的每一行计算一个随机数。这是因为它必须计算每一行的随机值,以便知道哪一行生成了最大值。因此,如果您有一个包含100000行的表,然后调用ORDER BY RAND() LIMIT 1。您正在告诉MySQL为100000行生成一个随机数,按照该数字对它们进行排序,然后给出第一个。
执行以下操作要快得多:
1.从Table中选择计数(
1.在您的脚本/编程语言中生成0和上述查询结果减去1之间的随机数。
1.从Table LIMIT random_number_此处选择
,1

qij5mzcb

qij5mzcb3#

基于快速测试,我必须得出结论,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)
cvxl0en2

cvxl0en24#

将为每行计算RAND()值,因此对于大型数据集来说,这不是很有效,LIMIT子句不会改变这一点。解决这个问题的通常方法是预先计算一个随机数,然后根据一些预先生成的索引列检索与之对应的行。
下面是一个详细的解释:
http://jan.kneschke.de/projects/mysql/order-by-rand/

yqlxgs2m

yqlxgs2m5#

ORDER BY大约是最后一个执行,但LIMIT是最后一次执行。
不幸的是,这意味着DB将为所有符合条件的行生成随机数,对它们排序,然后应用限制。
您可以做的是让表具有代理id字段,生成一个随机数,然后使用
SELECT x,y,z FROM table WHERE id >= your_rand_number

相关问题