Быстро выбрать случайный идентификатор из таблицы MySQL с миллионами непоследовательных записей
Я посмотрел вокруг, и, кажется, нет простого способа сделать это. Похоже, что проще получить набор записей и выполнить рандомизацию в коде (perl). Методы, которые я видел в Интернете, кажутся более чем сотнями тысяч, но, конечно, не миллионами.
Таблица, с которой я работаю, имеет 6 миллионов записей (и растет), идентификаторы автоматически увеличиваются, но не всегда сохраняются в таблице (без пробелов).
Я пытался выполнить запрос LIMIT 1, который был рекомендован, но этот запрос выполняется вечно - есть ли быстрый способ сделать это, учитывая наличие пробелов в записи? Я не могу просто взять максимум и рандомизировать в диапазоне.
Обновить:
Возможно, одна из моих идей заключалась в том, чтобы получить максимум, рандомизировать предел на основе максимума, а затем получить диапазон из 10 записей от random_limit_1 до random_limit_2 и затем взять первую запись, найденную в этом диапазоне.
Или, если я знаю максимум, есть ли способ, которым я могу просто выбрать, скажем, 5-ую запись таблицы, без необходимости знать, какой это идентификатор. Тогда просто захватывая идентификатор этой записи.
Обновить:
Этот запрос несколько быстрее. Все еще не достаточно быстро =/
SELECT t.id FROM table t JOIN (SELECT(FLOOR(max(id) * rand())) as maxid FROM table) as tt on t.id >= tt.maxid LIMIT 1
3 ответа
Да, идея кажется хорошей:
select min(ID), max(ID) from table into @min, @max;
set @range = @max - @min;
set @mr = @min + ((@range / 1000) * (rand() * 1000));
select ID from table
where ID >= @mr and ID <= @mr + 1000
order by rand()
limit 1
-- into @result
;
Может изменяться от 1000 до 10000 или как угодно, чтобы масштабироваться...
РЕДАКТИРОВАТЬ: вы также можете попробовать это:
select ID from table
where (ID % 1000) = floor(rand() * 1000)
order by rand()
limit 1
;
Разбивает его по разным линиям...
РЕДАКТИРОВАТЬ 2:
Смотрите: Каков наилучший способ выбрать случайную строку из таблицы в MySQL?
Это, вероятно, самый быстрый способ:
select @row := floor(count(*) * rand()) from some_tbl;
select some_ID from some_tbl limit @row, 1;
к сожалению, переменные нельзя использовать в предложении limit, поэтому вам придется использовать динамический запрос, либо записывая строку запроса в коде, либо используя PREPARE и EXECUTE. Кроме того, ограничение n, 1 по-прежнему требует сканирования n элементов в таблице, так что это всего лишь в два раза быстрее, чем второй метод, перечисленный выше в среднем. (Хотя это, вероятно, более равномерно и гарантирует, что соответствующая строка всегда будет найдена)
SELECT * FROM TABLE ORDER BY RAND() LIMIT 1;
Хорошо, это медленно. Если вы будете искать ORDER BY RAND() MYSQL
, вы найдете много результатов, говорящих, что это очень медленно, и это так. Я провел небольшое исследование и обнаружил, что эта альтернатива MySQL rand() работает медленно на больших наборах данных. Надеюсь, это лучше