У меня есть таблица с несколькими строками (вершины 50), мне нужно получить случайное значение из таблицы, я могу это сделать
ORDER BY RAND() LIMIT 1
Главный вопрос заключается в том, что, когда у меня 6k выбирает за 5 секунд, rand stil 'reliable'? Как рассчитывается ранд, могу ли я его посеять с течением времени? (idk, каждые 5 секунд).
Генератор псевдослучайных чисел MySQL полностью детерминирован. Документы говорят:
RAND () не предназначен для создания идеального случайного генератора. Это быстрый способ генерации случайных чисел по требованию, которые переносятся между платформами для одной и той же версии MySQL.
Он не может использовать / dev / random, потому что MySQL предназначен для работы с различными операционными системами, некоторые из которых не имеют / dev / random.
MySQL инициализирует семя по умолчанию при запуске сервера, используя целое число, возвращаемое по time(0)
. Если вас интересует исходная строка, она находится в источнике MySQL в файле sql / mysqld.cc, function init_server_components()
. Я не думаю, что он когда-либо перерабатывает себя.
Затем последующие «случайные» числа основаны исключительно на семени. См. Исходный файл mysys_ssl / my_rnd.cc, function my_rnd()
.
Лучшим решением для вашей задачи случайного выбора, как для производительности, так и для качества рандомизации, является генерация случайного значения между минимальным значением первичного ключа и максимальным значением первичного ключа. Затем используйте это случайное значение для выбора первичного ключа в таблице:
SELECT ... FROM MyTable WHERE id > $random LIMIT 1
Причина, по которой вы будете использовать> вместо =, состоит в том, что у вас могут быть пробелы в идентификаторе из-за удаления или отката строк или у вас могут быть другие условия в предложении WHERE, чтобы у вас были промежутки между строками, соответствующими вашим условиям ,
Недостатки этого большего, чем метода:
Преимущества этого метода:
RAND является псевдослучайным. Будьте осторожны, используя его для обеспечения безопасности. Я не думаю, что ваш «выбор одной строки случайным образом из пятидесяти» предназначен для обеспечения безопасности, поэтому вы, вероятно, в порядке.
Это довольно быстро для небольшого стола. Это будет ужасно для выбора случайной строки из большой таблицы: она должна будет пометить каждую строку псевдослучайным числом и затем отсортировать их. Для приложения, которое вы описываете, предложение TheEwook совершенно верно; сортировка даже небольшого стола чаще, чем один раз миллисекунда, может залить даже мощное оборудование MySQL.
Не помещайте RAND, когда-либо, если вы не тестируете, и вам нужна повторяемая последовательность случайных чисел для какого-либо модульного теста. Я усвоил этот трудный путь, когда создавал то, что, как я думал, было трудноопределяемым токенам сеанса. Ребята из MySQL хорошо поработали с RAND, и вы можете доверять им для приложения, о котором вы говорите.
Я думаю (не уверен), если вы не засеваете его, он начинается со случайного семени из / dev / random.
Если вам нужны крипторазмерные случайные числа, прочитайте / dev / random самостоятельно. Но имейте в виду, что / dev / random может генерировать только ограниченную скорость. / dev / urandom использует / dev / random для генерации более быстрой скорости, но не является полноценным в своем энтропийном пуле.
Если ваша таблица не слишком большая (скажем, 1000 записей), это не имеет большого значения. Но для больших таблиц вы должны выбрать альтернативный способ.
Эта статья может помочь вам:
http://www.titov.net/2005/09/21/do-not-use-order-by-rand-or-how-to-get-random-rows-from-table/