PHP取MySQL随机记录的两种高效方法

从数据库中随机取记录的需求应该还是不少的,网上流传的一些版本在记录多的时候性能都比较差。

性能差的版本

select * from table order by rand() limit 1

在这我分享两个PHP取MySQL随机记录的高效方法。

由于各个框架操作数据库的方法不一样,所以贴代码没任何意义,仅提供思路。

你可能需要PHP批量随机生成不重复数字的函数:http://blog.yurunsoft.com/a/23.html

方法一

自增主键:不依赖

特点:随机取出一条记录效率高

思路:

首先查询表记录数量,我们将表记录数存到$count变量中

select count(*) from table

$limit为随机取出数量,我们要随机出$limit个不重复的数字,取值范围是0到$count-1

$limits = randomNums(0, $count- 1, $limit);

比如$limits中现在是array(1,10,6,7,21),这时候遍历$limits去查询

$results = array();
foreach($limits as $limit)
{
    // 伪代码
    $results[] = 查询("select * from table limit {$limit},1");
}

本方法随机的是记录所在位置,然后分别到对应位置取出记录,所以随机一条记录比多条记录性能要高。

如果你是打算随机多条记录,请看方法二,性能更高哦!

方法二

自增主键:依赖

特点:随机取出多条记录效率高

思路:

首先,我们查出表中记录数量、自增主键最小值和最大值。

select count(*) as count,max(id) as max,min(id) as min

接下来我们应该批量随机主键值,那么随机多少个是个问题。

如果表里记录有被删除过,那么max和count的值是不等的,这时候如果从0到max之间去随机,有可能随机到被删除的记录的ID。最后取出来随机记录数量就不对了。

所以我们通过max-count算出被删除的记录数,加上随机多少条记录,这时候的随机数一定能满足随机记录数量。但是要注意,如果删除记录过多,也会影响效率。

$limitCount = $result['max'] - $result['count'] + $limit;

接下来我们随机出主键ID

$limits = randomNums($result['min'], $result['max'], $limitCount);

然后我们使用in来批量查询出数据,记得加上limit来限制数量,因为可能$limits不止$limit个

$limits = implode(',',$limits);
查询("select * from table where id in ({$limits}) limit {$limit}");

这时候,是随机取出数据了,但是记录顺序是根据id来的,这时候我们还需要再来改进。

$limits = implode(',',$limits);
查询("select * from table where id in ({$limits}) order by field(id,{$limits}) limit {$limit}");

使用order by field可以保证顺序是随机的,这个用法只支持MySQL

这两个方法在YurunPHP中早就已经内置,可以通过Model中的random和randomEx方法调用。

  • 标签
  • 发表评论
当前用户:
  • 评论列表
  • OneTake 2018-09-06 15:57:12

    顶一下