Быстро выбрать случайный идентификатор из таблицы 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() работает медленно на больших наборах данных. Надеюсь, это лучше

SELECT ID
    FROM YourTable
    ORDER BY RAND() LIMIT 1;
Другие вопросы по тегам