Avoiding use of RAND() in MySQL query in Kohana 3
I have never had a need to do a random SELECT on a MySQL DB until this project I'm working on. After researching it seems the general populous says that using RAND() is a bad idea. I found an article that explains how to do another type of random select.
Basically, if I want to select five (5) random elements, I should do the following (I'm using the Kohana framework here)?
<?php
final class Offers extends Model
{
/**
* Loads a random set of offers.
*
* @param integer $limit
* @return array
*/
public function random_offers($limit = 5)
{
// Find the highest offer_id
$sql = '
SELECT MAX(offer_id) AS max_offer_id
FROM offers
';
$max_offer_id = DB::query(Database::SELECT, $sql)
->execute($this->_db)
->get('max_offer_id');
// Check to make sure we're not trying to load more offers
// than there really is...
if ($max_offer_id < $limit)
{
$limit = $max_offer_id;
}
$used = array();
$ids = '';
for ($i = 0; $i < $limit; )
{
$rand = mt_rand(1, $max_offer_id);
if (!isset($used[$rand]))
{
// Flag the ID as used
$used[$rand] = TRUE;
// Set the ID
if ($i > 0) $ids .= ',';
$ids .= $rand;
++$i;
}
}
$sql = '
SELECT offer_id, offer_name
FROM offer开发者_如何学编程s
WHERE offer_id IN(:ids)
';
$offers = DB::query(Database::SELECT, $sql)
->param(':ids', $ids)
->as_object();
->execute($this->_db);
return $offers;
}
}
If not, what is a better solution?
That approach will work, as long as your offer_id's are sequential and all continuous - if you ever remove an offer, you might have gaps in the id's that would then be a problem.
I've read the same things about the MySQL rand() function on large table sets, but I would think you could do it faster by counting the table rows, then using PHP's built in rand(0, count) to generate a few index ID's you can grab in a SELECT. I suspect it would have the same affect but without all the performance concerns.
精彩评论