本帖最后由 love1989 于 2011-02-21 16:07:11 编辑

解决方案 »

  1.   

    SELECT t1.id FROM `user` AS t1 JOIN (SELECT ROUND(RAND() * (SELECT MAX(id) FROM `user`)) AS id) AS t2 WHERE t1.id>= t2.id ORDER BY t1.id ASC LIMIT 30;不过取出来的是连续的iD
      

  2.   

    抛弃order by rand(),取结果集抓换成数组处理会快很多
      

  3.   

    如果表中某个字段是连续的,先取最小值和最大值,然后生成30个介于最小值和最大值之间的数值,最后再select xx from table where xx in (生成的30个数值)
    仅供参考
      

  4.   

    抛弃order by rand(),取结果集抓换成数组处理会快很多
    ---------------------------------------------
    如果表中某个字段是连续的,先取最小值和最大值,然后生成30个介于最小值和最大值之间的数值,最后再select xx from table where xx in (生成的30个数值)
    仅供参考这两个方法都可以,各有优缺点。
    方法一,数据库10万级的没问题,上百万级服务器就吃不消了,内存消耗太大。方法二,字段必须是连续的,如果有过删除的话 字段就不连续,用这个方法就会取到空值。但这个方法速度快,服务器开销很小。
      

  5.   

    做一个函数,用方法2,就用PHP来生成30个随机数,取数据,不够的重复调用方法,直到满30个为止。
    大数据量下,比起使用SQL语句直接实现要快得多。
      

  6.   

    比较推崇方法二略做变形,如下:
    先取最小值和最大值,然后生成60个(也可50个或40个 视情况而定)介于最小值和最大值之间的数值,最后再select xx from table where xx in (生成的60个数值),然后去除掉空记录,取剩下的前30条。
    如果剩下的不足30条,那就再次调用这个过程取记录,直到满足共30条记录为止。
      

  7.   

    正好,之前有看到个order by rand()的优化,老外说即使innodb引擎都有10倍提升,我测试了下,数据越多,确实有更多提升,但是10倍提升还没测出来。
    你数据量大可以再帮我测试下
    SELECT i.userid FROM (
    SELECT @cnt := COUNT(*) + 1,
    @lim := 30
    FROM users
    ) vars STRAIGHT_JOIN(
    SELECT r.*,
    @lim := @lim - 1
    FROM users r
    WHERE (@cnt := @cnt - 1)
    AND RAND() < @lim / @cnt
    ) i
      

  8.   

    只取userid,可以再改改
    SELECT i.userid FROM (
    SELECT @cnt := COUNT(*) + 1,
    @lim := 30
    FROM users
    ) vars STRAIGHT_JOIN(
    SELECT r.userid,
    @lim := @lim - 1
    FROM users r
    WHERE (@cnt := @cnt - 1)
    AND RAND() < @lim / @cnt
    ) i