Mysql 列X为Y的最快随机选择(空)

Mysql 列X为Y的最快随机选择(空),mysql,sql,Mysql,Sql,目前我正在使用: 选择* 从…起 表AS t1 参加 选择RAND*从表格中选择MAXid,其中列x作为id为null AS t2 哪里 t1.id>=t2.id 列x为空 按t1.id ASC订购 限制1 这通常是非常快的,但是当我包括高亮显示的列_x为Y空条件时,它会变慢 当记录的X列为空时,最快的随机查询解决方案是什么 ID是PK,X列是int4。该表包含大约一百万条记录,总容量超过1GB,目前每24小时翻一番 列_x被索引 列ID不能是连续的 本例中使用的DB引擎是InnoDB 谢谢。您

目前我正在使用:

选择* 从…起 表AS t1 参加 选择RAND*从表格中选择MAXid,其中列x作为id为null AS t2 哪里 t1.id>=t2.id 列x为空 按t1.id ASC订购 限制1 这通常是非常快的,但是当我包括高亮显示的列_x为Y空条件时,它会变慢

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

ID是PK,X列是int4。该表包含大约一百万条记录,总容量超过1GB,目前每24小时翻一番

列_x被索引

列ID不能是连续的

本例中使用的DB引擎是InnoDB

谢谢。

您对查询进行了解释吗?输出是什么

为什么不存储或缓存的值:从列x为null的表中选择MAXid并将其用作变量。您的查询将变成:

$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
在数据库上,一个更简单的查询可能会更容易


要知道,如果您的数据包含相当大的漏洞,那么您将无法通过此类查询获得一致的随机结果。

获得真正的随机记录可能会很慢。事实上,没有什么可以回避这个事实;如果希望它是真正随机的,那么查询必须加载所有相关数据,以便知道它必须从哪些记录中进行选择

然而幸运的是,有更快的方法可以做到这一点。它们不是完全随机的,但是如果你愿意用一点纯粹的随机性来换取速度,那么它们在大多数情况下都应该足够好

考虑到这一点,获取随机记录的最快方法是向数据库中添加一个额外的列,其中填充了一个随机值。也许是主键的一个咸MD5散列?无论什么在该列上添加适当的索引,然后只需将该列添加到查询中的ORDERBY子句中,就可以以随机顺序取回记录

要获得单个随机记录,只需指定限制1并添加WHERE random_字段>$random_值,其中random值将是新字段范围内的值,例如,随机数的MD5散列

当然,不利的一面是,尽管您的记录将以随机顺序排列,但它们将以相同的随机顺序排列。我说过这是用完美来换取查询速度。你可以通过定期用新的值更新它们来解决这个问题,但我想如果你需要保持它的新鲜度,这可能是一个问题

另一个不利的方面是,如果您有存储限制,并且您的数据库已经很大,或者在添加列之前需要经过严格的DBA,那么添加额外的列可能会太多。但同样,你必须交换一些东西;如果您想要查询速度,您需要这个额外的列


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

如果ID是唯一的,我认为您不需要加入、订购人或限制1

SELECT *
FROM   myTable
WHERE  column_x IS NULL
   AND id = ROUND(RAND() * (SELECT MAX(Id) FROM myTable), 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;

是的,它被索引了,但是随着数据库的增长,查询开始花费太长的时间,并且很多列_x变为非空。该表是使用MyISAM还是InnoDB引擎?你能试着在列_x,id上添加一个复合索引吗?你能编辑你的问题并添加解释计划吗?带有Order By的行有一个拼写错误,对吗?应该是:orderbyt1.id ashello,这是一个输入错误。现在修好了。谢谢。除了id不是顺序的,因此它将返回1或0行。id不需要是顺序的-但请再次查看-如果行的id具有列_x值,则不会返回任何内容-因此我将进行另一次查看。您好,不幸的是,当涉及列时,此查询无法工作。它将返回空,因为0和列X为NULL的记录的最大ID之间的随机ID可能属于列X不为NULL的列。但是,您可以使用和ID>=。。。限制1。问题中的查询中的连接是不必要的。这是迄今为止提出的唯一一种提供真正统一概率的方法。ID中的间隙无关紧要。易于实现和索引+1A偏移量大的查询效率很低,X列的值不断变化。在每次查询中,都必须检查所有列_x,以确定哪些列仍然为空。这听起来有点奇怪,但不会改变我的答案-您实际上不需要在MAXid查询中输入列_x为空。在罕见的情况下,您没有得到任何结果,您只需再次查询反转逻辑测试t1.id<$rand即可。您仍然需要将解释结果添加到问题中。