быстрый выбор случайной строки из большой таблицы в MySQL - PullRequest
44 голосов
/ 17 октября 2008

Какой быстрый способ выбрать случайную строку из большой таблицы MySQL?

Я работаю в php, но меня интересует любое решение, даже если оно на другом языке.

Ответы [ 24 ]

0 голосов
/ 15 мая 2015

В моем случае в качестве первичного ключа у моей таблицы есть идентификатор, автоинкремент без пробелов, поэтому я могу использовать COUNT(*) или MAX(id) для получения количества строк.

Я сделал этот скрипт для проверки самой быстрой операции:

logTime();
query("SELECT COUNT(id) FROM tbl");
logTime();
query("SELECT MAX(id) FROM tbl");
logTime();
query("SELECT id FROM tbl ORDER BY id DESC LIMIT 1");
logTime();

Результаты:

  • Количество: 36.8418693542479 ms
  • Макс .: 0.241041183472 ms
  • Заказ : 0.216960906982 ms

Ответ с методом заказа:

SELECT FLOOR(RAND() * (
    SELECT id FROM tbl ORDER BY id DESC LIMIT 1
)) n FROM tbl LIMIT 1

...
SELECT * FROM tbl WHERE id = $result;
0 голосов
/ 20 декабря 2008

Я немного новичок в SQL, но как насчет генерации случайного числа в PHP и использования

SELECT * FROM the_table WHERE primary_key >= $randNr

это не решает проблему с отверстиями в таблице.

Но вот предложение Лассевкс:

SELECT primary_key FROM the_table

Используйте mysql_num_rows () в PHP, создайте случайное число на основе приведенного выше результата:

SELECT * FROM the_table WHERE primary_key = rand_number

На заметку о том, насколько медленно SELECT * FROM the_table:
Создание случайного числа на основе mysql_num_rows() с последующим перемещением указателя данных в эту точку mysql_data_seek(). Насколько медленно это будет на больших таблицах, скажем, с миллионами строк?

0 голосов
/ 29 марта 2017

Создайте функцию, чтобы сделать это, скорее всего, лучшим ответом и самым быстрым ответом здесь!

Плюсы - работает даже с пробелами и очень быстро.

<?

$sqlConnect = mysqli_connect('localhost','username','password','database');

function rando($data,$find,$max = '0'){
   global $sqlConnect; // Set as mysqli connection variable, fetches variable outside of function set as GLOBAL
   if($data == 's1'){
     $query = mysqli_query($sqlConnect, "SELECT * FROM `yourtable` ORDER BY `id` DESC LIMIT {$find},1");

     $fetched_data = mysqli_fetch_assoc($query);
      if(mysqli_num_rows($fetched_data>0){
       return $fetch_$data;
      }else{
       rando('','',$max); // Start Over the results returned nothing
      }
   }else{
     if($max != '0'){
        $irand = rand(0,$max); 
        rando('s1',$irand,$max); // Start rando with new random ID to fetch
     }else{

        $query = mysqli_query($sqlConnect, "SELECT `id` FROM `yourtable` ORDER BY `id` DESC LIMIT 0,1");
        $fetched_data = mysqli_fetch_assoc($query);
        $max = $fetched_data['id'];
        $irand = rand(1,$max);
        rando('s1',$irand,$max); // Runs rando against the random ID we have selected if data exist will return
     }
   }
 }

 $your_data = rando(); // Returns listing data for a random entry as a ASSOC ARRAY
?>

Пожалуйста, имейте в виду, что этот код не был протестирован, но он является рабочей концепцией для возврата случайных записей даже с пробелами. Пока пробелы недостаточно велики, чтобы вызвать проблему времени загрузки.

0 голосов
/ 21 марта 2009

Взгляните на эту ссылку Яна Кнешке или этот SO-ответ , поскольку они оба обсуждают один и тот же вопрос. Ответ SO также включает в себя различные варианты и предлагает несколько хороших предложений в зависимости от ваших потребностей. Ян рассматривает все варианты и характеристики каждого из них. Он заканчивает следующим для наиболее оптимизированного метода, чтобы сделать это в выборе MySQL:

SELECT name
  FROM random AS r1 JOIN
       (SELECT (RAND() *
                     (SELECT MAX(id)
                        FROM random)) AS id)
        AS r2
 WHERE r1.id >= r2.id
 ORDER BY r1.id ASC
 LIMIT 1;

НТН,

-Dipin

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...