开发者

Avoiding use of RAND() in MySQL query in Kohana 3

开发者 https://www.devze.com 2022-12-29 14:23 出处:网络
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

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消