Php 优化随机记录查询

Php 优化随机记录查询,php,mysql,Php,Mysql,我对这个问题有疑问……或者,还没有我很快会问的那么多。目前,“marketingDatabase”表的行数约为11000行,但在下个月内,该表的行数可能会接近100000行,到3月份可能会增长到500000行 我知道使用ORDER BY RAND()不是一个好办法,但这是我唯一能做的事情。我尝试过其他的事情,但第一次的陈述似乎让我很反感。我使用的是PHP,所以我也可以用PHP处理其中的一些内容 使用此查询,从符合WHERE语句的行中选择随机行的最佳方法是什么 问题是: SELECT id FRO

我对这个问题有疑问……或者,还没有我很快会问的那么多。目前,“marketingDatabase”表的行数约为11000行,但在下个月内,该表的行数可能会接近100000行,到3月份可能会增长到500000行

我知道使用ORDER BY RAND()不是一个好办法,但这是我唯一能做的事情。我尝试过其他的事情,但第一次的陈述似乎让我很反感。我使用的是PHP,所以我也可以用PHP处理其中的一些内容

使用此查询,从符合WHERE语句的行中选择随机行的最佳方法是什么

问题是:

SELECT id
FROM `marketingDatabase`
WHERE do_not_call != 'true'
  AND status = 'Pending'
  AND install_id = 'AN ID HERE'
  AND NOT EXISTS(
    SELECT recordID
    FROM reminders rem
    WHERE rem.id = marketingDatabase.id
)
ORDER BY rand()
LIMIT 1

你有没有想过如何让这项工作做得更好?我只需要一个随机的“id”。

我们遇到了与您现在面临的问题相同的问题,行数增长太多,按rand()排序实际上导致连接挂起并抛出白页,因此我们必须想出不同的解决方案

我们采取的一种选择是将id分为1000个组,并将它们放入缓存,然后我们将随机选择哪个组,然后随机选择要选择的组中的哪个id

我们还每天向一个平面文件写入一个随机ID样本,并从中读取数字,但我相信,对于以前的缓存解决方案,我们不再使用该解决方案


只是一些想法。

首先,看看我们是否可以优化一下该查询:

SELECT `m`.`id`
FROM `marketingDatabase` AS `m`
  LEFT JOIN `reminders` AS `r` ON ( `r`.`id` = `m`.`id` )
WHERE
  `m`.`do_not_call` != 'true'
  AND `m`.`status` = 'Pending'
  AND `m`.`install_id` = 'AN ID HERE'
  AND `r`.`id` IS NULL
ORDER BY
  rand()
LIMIT 1
注意:这只是一个想法,还没有在野外测试过

为什么不获取要查找的可能记录数的计数,然后使用PHP从该计数中查找一个随机行数,然后重新查询以查找它呢

$rowCount = 0;

$rowCountSql = "SELECT COUNT(*) AS `rowcount`
  FROM `marketingDatabase` AS `m`
    LEFT JOIN `reminders` AS `r` ON ( `r`.`id` = `m`.`id` )
  WHERE
    `m`.`do_not_call` != 'true'
    AND `m`.`status` = 'Pending'
    AND `m`.`install_id` = 'AN ID HERE'
    AND `r`.`id` IS NULL";

if( $rowCountRes = mysql_query( $rowCountSql )
    && mysql_num_rows( $rowCountRes )
    && $r = mysql_fetch_assoc( $rowCountRes ) )
  $rowCount = $r['rowcount'];

$oneRow = false;

$oneRowSql = "SELECT `m`.`id` AS `rowid`
  FROM `marketingDatabase` AS `m`
    LEFT JOIN `reminders` AS `r` ON ( `r`.`id` = `m`.`id` )
  WHERE
    `m`.`do_not_call` != 'true'
    AND `m`.`status` = 'Pending'
    AND `m`.`install_id` = 'AN ID HERE'
    AND `r`.`id` IS NULL
  LIMIT ".(int) $rowCount.", 1";

if( $oneRowRes = mysql_query( $rowCountSql )
    && mysql_num_rows( $oneRowRes )
    && $r = mysql_fetch_assoc( $oneRowRes ) )
  $oneRow = $r['rowid'];
这可能不会给绩效带来任何好处,但我只是想把它公布出来,看看我那些更博学的同事是否能改进它

对上述内容的进一步探讨(如果我有权访问您的数据库,我将对其进行测试…)


只是一个想法…

可能与@user969352重复,我的查询与顶部的Lucanos完全相同。。。唯一没有特别说明的补充是,通过将最小粒度的索引作为键的第一部分来优化查询。。。在这种情况下,我将有索引(Install\u ID、Status、Do\u Not\u Call)。
SELECT `m`.`id` AS `rowid`
  FROM `marketingDatabase` AS `m`
    LEFT JOIN `reminders` AS `r` ON ( `r`.`id` = `m`.`id` )
  WHERE
    `m`.`do_not_call` != 'true'
    AND `m`.`status` = 'Pending'
    AND `m`.`install_id` = 'AN ID HERE'
    AND `r`.`id` IS NULL
  LIMIT ( FLOOR( RAND( ) * (
    SELECT COUNT(*) AS `rowcount`
    FROM `marketingDatabase` AS `m`
      LEFT JOIN `reminders` AS `r` ON ( `r`.`id` = `m`.`id` )
    WHERE
      `m`.`do_not_call` != 'true'
      AND `m`.`status` = 'Pending'
      AND `m`.`install_id` = 'AN ID HERE'
      AND `r`.`id` IS NULL ) ) ) , 1