我当前的查询看起来像
SELECT *
FROM uploads
WHERE approved = 1
AND (up-down) >= 3
ORDER BY RAND()
LIMIT 10
这是从DB中随机选择10个条目,其中至少有3个不喜欢。
问题是因为我在DB中有超过40k的条目,这个查询需要1秒钟。
我在谷歌上看了很多但到目前为止没有找到任何东西。
在我的情况下你有什么选择吗?
答案 0 :(得分:1)
如果您要将所有匹配的记录加载到内存中,并且如果它们中没有太多,那么最简单的答案就是将order by
放入SQL中,然后对它们进行排序随机在您的应用软件中。例如,如果你正在使用PHP,你只需将它们全部加载到一个数组中,然后调用array_rand()
。
如果这不是合适的答案,那么您仍然需要在数据库中对它们进行排序,那么在order by rand()
太慢的情况下(即大多数情况下您有大量数据) ,我所知道的最佳解决方案如下:
向表中添加一个新列,并使用每个记录的主键的MD5哈希预填充它。并添加一个索引以按新字段排序。
这将为您提供表格的均匀分布的随机排序顺序。只需order by
此字段代替rand()
。
答案 1 :(得分:0)
最佳方法取决于许多因素。以下是一些想法。
假设没有索引,当前版本的查询正在进行全表扫描,提取行,分配随机数,对行进行排序,然后选择前10个。
全表扫描第一次可能很慢,但在此之后应该非常快,假设表适合内存。我假设您的性能问题不是指查询的第一个实例,而是指该表已经在页面缓存中的那个。
如果“已批准”具有高度选择性 - 例如,1%的行已获批准 - 那么您可以通过在已批准的情况下构建索引来加快查询速度。
下一个选择是为“up-down”添加一列,并在两个密钥和已批准的UpMinusDown上构建索引。假设这是选择性的,它可以降低速度。
接下来的问题是,您是否可以将rand()
替换为其他一些标准 - 例如,最新的10个标准。如果是这样,您可以包含一个主键说上载ID并将其用于排序。它会更快。
最后,如果您的记录非常广泛,那么它可能会占用时间。在这种情况下,我想知道以下版本的查询是否会表现更好:
SELECT *
FROM uploads u left outer join
(select UploadID
from uploads
WHERE approved = 1
AND (up-down) >= 3
ORDER BY RAND()
LIMIT 10
) random
on u.UploadID = random.UploadID
(这假设您在表上有一个名为UploadID的主键。)
此版本应仅对UpLoadID进行排序,然后使用索引将其连接回原始数据。