目前我正在使用:
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。
谢谢。
答案 0 :(得分:3)
获得真正随机的记录可能会很慢。这个事实并没有真正解决这个问题;如果你想让它真正随机,那么查询必须加载所有相关数据,以便知道它必须选择哪些记录。
幸运的是,有更快捷的方法。它们并不是随意的,但是如果你乐于换取一点纯随机性来提高速度,那么它们应该足以满足大多数用途。
考虑到这一点,获取“随机”记录的最快方法是在数据库中添加一个额外的列,该列填充了随机值。也许主键的盐渍MD5哈希?随你。在此列上添加适当的索引,然后只需将该列添加到查询中的ORDER BY
子句中,您将以随机顺序返回记录。
要获取单个随机记录,只需指定LIMIT 1
并添加WHERE random_field > $random_value
,其中随机值将是新字段范围内的值(例如随机数的MD5哈希值,对于例子)。
当然,这里的缺点是虽然你的记录将是随机顺序,但它们会被卡在相同的随机顺序中。我确实说它是查询速度的完美交易。您可以通过使用新值定期更新它们来解决这个问题,但我想如果您需要保持新鲜,那么这对您来说可能是一个问题。
另一个缺点是添加一个额外的列可能太多了,无法询问您是否存在存储限制,并且您的数据库规模已经很大,或者您是否有一个严格的DBA可以在添加列之前通过。但同样,你必须权衡一些事情;如果你想要查询速度,你需要这个额外的列。
无论如何,我希望有所帮助。
答案 1 :(得分: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
db上更简单的查询可能会更容易。
要知道,如果您的数据包含相当大的漏洞 - 您不会通过这类查询得到一致的随机结果。
答案 2 :(得分:1)
我认为您不需要加入,也不需要订单,也不需要限制1(提供ID是唯一的)。
SELECT *
FROM myTable
WHERE column_x IS NULL
AND id = ROUND(RAND() * (SELECT MAX(Id) FROM myTable), 0)
答案 3 :(得分: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;