测试MySQL 实现随机查询的最优方案

Mysql自带的rand()在数据量少时还是比较方便的,当数据量一大效率问题就会凸显。

网上有一篇 MySQL rand函数实现随机数的方法“http://database.51cto.com/art/201010/229217.htm

文中介绍使用max(id) * rand()再取整来随机获取数据,这种方案在一定程度上缩短了搜索的范围,另外是顺序读取的,所以效率不错。

来看两个完整的例子

 

#例子1
select * from  pre_common_member where  uid<>1 and uid>(SELECT FLOOR(RAND() * (SELECT MAX(UID) FROM pre_common_member)))   limit 9

#例子2
SELECT *  FROM pre_common_member  AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(uid) FROM pre_common_member )) AS uid) AS t2  WHERE t1.uid >= t2.uid LIMIT 9

 

文章中也说了这样会产生连续的5条记录。解决办法只能是每次查询一条,查询多次。不过加起来速度还是不错的。

这里还会有一个问题,如果恰巧随机到了最大值,那limit出来的就不满9条,这里通过后面的办法会适当避免。

 

如果细细研究会发现上面的SQL只限制了搜索的范围的下限,如果再加上上限会不会更好呢?

先来看两个explain的结果

 

mysql> explain select * from  pre_common_member where  uid<>1 and uid>506203   limit 9\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: pre_common_member
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 3
          ref: NULL
         rows: 150470
        Extra: Using where
1 row in set (0.00 sec)

mysql> explain select * from  pre_common_member where  uid<>1 and uid>506203 and uid<516203   limit 9\G
*************************** 1. row ***************************
           id: 1
  select_type: SIMPLE
        table: pre_common_member
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 3
          ref: NULL
         rows: 7541
        Extra: Using where
1 row in set (0.00 sec)

从上面可以看到搜索上限和下限都加上后效果很明显,且不会随着数据量的扩大而增加搜索范围。

为了更形象的比较,写了一个PHP的测试文件,具体代码见附件

t.php

测试结果

 

方案1:0.039853096008301
方案2:0.0343918800354
方案3:0.0094499588012695
方案4:0.017409086227417

所以利用开发语言缩小搜索的范围的达到了速度的最优化。这正是我们需要的。另外这还解决了随机到最大值的问题。

Tags: rand , mysql

上一篇: 在线反编译php,java,flash,dotnet   下一篇: 【转】开发一个PHP扩展入门

提交疑问

回顶部