我正在寻找一种有效的方法,从MySQL表中随机选择满足某些条件的100行,可能有数百万行。
我发现的几乎所有内容都建议避免使用ORDER BY RAND(),因为性能和可伸缩性都很差。
然而,this article表明ORDER BY RAND()仍然可以用作一种“快速而快速的方式”。获取randow数据。
基于这篇文章,下面是一些示例代码,展示了我想要完成的任务。我的问题是:
这是从表格中随机选择100行(或最多数百行)的有效方式吗?
性能何时成为问题?
SELECT user.* FROM ( SELECT id FROM user WHERE is_active = 1 AND deleted = 0 AND expiretime > '.time().' AND id NOT IN (10, 13, 15) AND id NOT IN (20, 30, 50) AND id NOT IN (103, 140, 250) ORDER BY RAND() LIMIT 100 ) AS random_users STRAIGHT JOIN user ON user.id = random_users.id
答案 0 :(得分:1)
强烈建议您阅读此article。最后一段将涵盖多个随机行的选择。您应该能够注意到SELECT
中将要描述的PROCEDURE
语句。这将是您添加特定WHERE
条件的地方。
ORDER BY RAND()
的问题是此操作具有n*log2(n)
的复杂性,而我链接的文章中描述的方法几乎具有复杂性。
让我们假设,使用ORDER BY RAND()
从表中选择包含10个条目的随机行需要1 time unit
:
entries | time units
-------------------------
10 | 1 /* if this takes 0.001s */
100 | 20
1'000 | 300
10'000 | 4'000
100'000 | 50'000
1'000'000 | 600'000 /* then this will need 10 minutes */
你写道,你正在处理数百万的表。
答案 1 :(得分:0)
我担心没有人能够准确地回答你的问题。如果你真的想知道你需要对你的系统运行一些基准测试(理想情况下不是实时的,而是精确的副本)。针对不同的解决方案(例如使用PHP获取随机行)对这个解决方案进行基准测试,并将数字与您/您的客户认为“良好性能”的数据进行比较。然后提高数据量,以保持列值的分布接近真实你可以,看看性能开始下降的地方。说实话,如果它现在有一点空间,那么我会去做它。当(如果!)它成为瓶颈然后你可以看看它再次 - 或者只是在你的数据库中掏出额外的铁......
答案 2 :(得分:0)
尽可能预处理 尝试类似(类似VB的例子)
Dim sRND = New StringBuilder : Dim iRandom As New Random()
Dim iMaxID As Integer = **put you maxId here**
Dim Cnt as Integer=0
While Cnt < 100
Dim RndVal As Integer = iRandom.Next(1, iMaxID)
If Not ("10,13,15,20,30,50,103,140,250").Contains(RndVal) Then
Cnt += 1
sRND.Append("," & RndVal)
end if
End While
String.Format("SELECT * FROM (Select ID FROM(User) WHERE(is_active = 1) AND deleted = 0 AND expiretime > {0} AND id IN ({1}) .blahblablah.... LIMIT 100",time(), Mid(sRND.ToString, 2))
我没有检查语法,但我希望你能得到我的漂移。 这将使MySql读取符合“IN”的记录,并在达到100时停止,而无需首先预处理所有记录。
如果你试试,请告诉我经过时间的差异。 (我很谨慎)