根据50k行表中的要求选择随机行。太慢了。我怎样才能加快速度?

时间:2014-03-18 01:14:15

标签: php mysql

我有一张约有5万行的表格。有一个名为status的列。其值可以是01。我需要抓取一个status = 0的随机行。

SELECT * FROM table WHERE status = 0 ORDER BY RAND() LIMIT 1显然太慢了。

所以,我到目前为止所做的是,使用status = 0

计算SELECT COUNT(status) FROM table WHERE status = 0的行数

现在我现在有209行status = 0,但我如何处理这些行?

我想订购这209行,并让我的php脚本在数字0和209之间得到一个随机的行号,但我不确定我是如何实现的......

2 个答案:

答案 0 :(得分:1)

你试过这个吗?

SELECT t.*
FROM table t
WHERE status = 0
ORDER BY RAND()
LIMIT 1;

排序209应该非常快。

编辑:

有效获取随机值具有挑战性。如果您在table(status)上有索引,则可以尝试这样的方法:

SELECT t.*
FROM table t cross join
     (select count(*) as allcnt from table where status = 0) const
WHERE status = 0 and
      RAND() < 10/allcnt
ORDER BY RAND()
LIMIT 1;

rand()子句中的where非常快(RAND()很快,排序很慢)。它应该将行数大大减少到预期值10 - 这意味着当你运行它时,你几乎肯定会得到一行(99.99 +%,我认为)。这比变量​​方法简单。

变量方法涉及一个子查询,它会产生自己的读取和写入派生表的开销。我们的想法是枚举行,然后随机选择一个索引:

SELECT t.*
FROM (select t.*, @rn := @rn + 1 as rn
      from table t cross join
           (select @rn := 0, @rand := rand()) const
      where status = 0
     ) t cross join
     (select count(*) as allcnt from table where status = 0) const
WHERE floor(1 + @rand * const.allcnt) = rn;

答案 1 :(得分:0)

我知道这需要两个查询,但你可以试一试并对它进行基准测试:得到匹配status = 0的行的总数,从0到该数字-1之间从PHP获得一个随机数,做一个选择限制为1的查询和php生成的随机值的偏移量。