3

我当前的查询看起来像这样

SELECT *
FROM uploads
WHERE approved = 1
    AND (up-down) >= 3
ORDER BY RAND()
LIMIT 10

这是从 DB 中随机选择 10 个条目,其中至少 3 个喜欢多于不喜欢。

问题是因为我在 DB 中有超过 40k 条目,而这个查询需要 1 秒。

我在谷歌上读了很多,但到目前为止没有找到任何东西。

在我的情况下,您有什么替代方案可以推荐吗?

4

2 回答 2

1

如果您将所有匹配的记录加载到内存中,并且它们的数量不多,那么最简单的答案就是将其order by放入您的 SQL 中,并在您的应用程序软件中对它们进行随机排序。例如,如果您使用的是 PHP,您可以简单地将它们全部加载到一个数组中,然后调用array_rand().

如果这不是一个合适的答案,那么您仍然需要在数据库中对它们进行排序,那么在order by rand()太慢的情况下(即大多数情况下您有大量数据),我所知道的最佳解决方案是如下:

向您的表中添加一个新列,并使用每条记录的主键的 MD5 哈希预填充它。并添加一个索引以按新字段排序。

这将为您提供表的均匀分布的随机排序顺序。只需order by此字段而不是rand().

于 2012-09-16T17:02:27.687 回答
0

最佳方法取决于许多因素。这里有一些想法。

假设没有索引,当前版本的查询正在执行全表扫描、提取行、分配随机数、对行进行排序,然后选择其中的前 10 个。

全表扫描第一次可能很慢,但之后应该会很快,假设表适合内存。让我假设您的性能问题不是指查询的第一个实例,而是指表已经在页面缓存中的一个实例。

如果“已批准”具有高度选择性——例如,1% 的行被批准——那么您可以通过在已批准上建立索引来加快查询速度。

下一个替代方法是为“up-down”添加一列,并在两个键上建立索引,approved 和 UpMinusDown。假设这是选择性的,它可以降低速度。

下一个问题是您是否可以用rand()其他一些标准替换 —— 例如,最近的 10 个。如果是这样,您可以包含一个主键,例如 UploadID 并将其用于排序。它会走得更快。

最后,如果您的记录非常广泛,那么它可能会占用时间。在这种情况下,我想知道以下版本的查询是否会执行得更好:

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 进行排序,然后使用索引将其连接回原始数据。

于 2012-09-16T16:58:32.807 回答