1

I've been using order by rand() and it's becoming too much of a bottle neck.

I've tried this

SELECT id
FROM users
JOIN (
  SELECT CEIL( RAND( ) * ( SELECT MAX( id ) FROM users ) ) AS id
) AS r2
  USING ( id )

And it would work if all the id's were incremented, however with this particular table, they're not. The id's are fairly random themselves.

Anyone have a better method? Thanks!

Peter Lang
  • 54,264
  • 27
  • 148
  • 161
dzm
  • 22,844
  • 47
  • 146
  • 226
  • possible duplicate of [How to request a random row in SQL?](http://stackoverflow.com/questions/19412/how-to-request-a-random-row-in-sql) – Peter Lang Sep 02 '10 at 07:58

5 Answers5

1

Maybe create another table and put there all id's in compact way, adding id int autoincrement? If you using this function often, new table will pay for itself.

alxx
  • 9,897
  • 4
  • 26
  • 41
  • That's not a bad idea actually, so then I can use the improved query I posted but do it based off the autoincrement column - Good idea! Will try that. – dzm Sep 02 '10 at 19:54
  • Don't forget to add trigger to update compact table when original table is updated. – alxx Sep 03 '10 at 06:27
1

Raveren: should be faster...

$ids = mysql::getSingleColumn('query');

$limit = 3;
shuffle($ids);

for($i=0;$<$limit;$i++)
  $usedIds[] = $ids[$i];

$idClause = implode(',',$usedIds);
Cristi
  • 11
  • 1
0

well if you have a lot of rows order by rand() is strongly NOT recommended because each row needs to have the random number calculated before the resultset can be ordered.

Maybe have a look at this -> http://www.electrictoolbox.com/msyql-alternative-order-by-rand/

Christophe
  • 4,798
  • 5
  • 41
  • 83
0

This is code I use for a quite performance-critical place in our application and it's benchmarked to perform way faster than order by rand():

$ids = mysql::getSingleColumn("select id from table where simple_where_clause = 'value'");

$limit = 3;

for ($i = 0;$i<$limit;$i++) {
    $r = rand( 0, count( $ids ) );
    if (isset($ids[$r])) {
        $usedIds[] = $ids[$r];
        unset($ids[$r]);
    } else {
        $i--;
    }
}
$idClause = implode(',',$usedIds);

I then use the $idClause in the main query: [...] WHERE id in ({$idClause})

raveren
  • 17,799
  • 12
  • 70
  • 83
-1

You can use this (it has some downsides)

SELECT id FROM users ORDER BY RAND() LIMIT 0,1

Mysql reference

Tim
  • 9,351
  • 1
  • 32
  • 48