2

目前我正在使用:

SELECT * 
FROM 
  table AS t1
  JOIN (
    SELECT (RAND() * (SELECT MAX(id) FROM table where column_x is null)) AS id
  ) AS t2 
WHERE 
  t1.id >= t2.id
  and column_x is null
ORDER BY t1.id ASC
LIMIT 1

这通常非常快,但是当我将突出显示的 column_x 包含为 Y(null)条件时,它会变慢。

记录的列 X 为空时,最快的随机查询解决方案是什么?

ID 是 PK,X 列是 int(4)。表包含大约一百万条记录和超过 1 GB 的总大小,目前每 24 小时翻一番。

column_x 已编入索引。

列 ID 可能不连续。

在这种情况下使用的数据库引擎是 InnoDB。

谢谢你。

4

4 回答 4

3

获得真正随机的记录可能会很慢。这个事实并没有太多的解决方法。如果您希望它是真正随机的,那么查询必须加载所有相关数据才能知道它必须从哪些记录中进行选择。

然而幸运的是,有更快的方法来做到这一点。它们不是完全随机的,但如果你乐于用一些纯粹的随机性来换取速度,那么它们对于大多数用途来说应该足够好。

考虑到这一点,获得“随机”记录的最快方法是向您的数据库添加一个额外的列,该列填充随机值。也许是主键的盐渍 MD5 散列?任何。在此列上添加适当的索引,然后只需将该列添加到ORDER BY查询中的子句中,您就会以随机顺序获取记录。

要获取单个随机记录,只需指定LIMIT 1并添加一个WHERE random_field > $random_valuewhere 随机值,该值将是新字段范围内的值(例如,随机数的 MD5 散列)。

当然,这里的缺点是,尽管您的记录将按随机顺序排列,但它们将被卡在相同的随机顺序中。我确实说过这是用完美换取查询速度。您可以通过定期使用新值更新它们来解决此问题,但我想如果您需要保持新鲜,这对您来说可能是个问题。

另一个缺点是,如果您有存储限制并且您的数据库已经非常庞大,或者您是否有一个严格的 DBA 需要通过才能添加列,那么添加一个额外的列可能太多了。但同样,你必须权衡一些东西;如果你想要查询速度,你需要这个额外的列。

无论如何,我希望这会有所帮助。

于 2012-05-20T22:47:59.510 回答
1

你跑过explain查询吗?输出是什么?

为什么不存储或缓存 : 的值SELECT MAX(id) FROM table where column_x is null并将其用作变量。您的查询将变为:

$rand = rand(0, $storedOrCachedMaxId);

SELECT * 
FROM 
  table AS t1
WHERE 
  t1.id >= $rand
  and column_x is null
ORDER BY t1.id ASC
LIMIT 1

在数据库上更简单的查询可能会更容易。

知道如果您的数据包含相当大的漏洞 - 您将不会通过此类查询获得一致的随机结果。

于 2012-05-20T22:44:11.230 回答
1

我认为您不需要加入,也不需要 order by,也不需要限制 1(前提是 id 是唯一的)。

SELECT *
FROM   myTable
WHERE  column_x IS NULL
   AND id = ROUND(RAND() * (SELECT MAX(Id) FROM myTable), 0)
于 2012-05-20T22:49:06.403 回答
0

我是 MySQL 语法的新手,但进一步挖掘我认为动态查询可能会起作用。我们选择第 N 行,其中第 N 行是随机的:

SELECT @r := CAST(COUNT(1)*RAND() AS UNSIGNED) FROM table WHERE column_x is null;

PREPARE stmt FROM
'SELECT * 
FROM table
WHERE column_x is null
LIMIT 1 OFFSET ?';

EXECUTE stmt USING @r;
于 2012-05-20T23:39:38.457 回答