Здесь очень интересное обсуждение этого типа вопроса: http://www.titov.net/2005/09/21/do-not-use-order-by-rand-or-how-to-get-random-rows-from-table/
Я думаю, что абсолютно без предположений относительно таблицы, что ваше решение O (n lg n) является лучшим. Хотя на самом деле, с хорошим оптимизатором или немного другой техникой, запрос, который вы перечисляете, может быть немного лучше, O (m * n), где m - желаемое количество случайных строк, так как необязательно сортировать весь большой массив. , он может просто искать самые маленькие m раз. Но для тех номеров, которые вы опубликовали, m больше, чем lg n.
Три предположения, которые мы могли бы опробовать:
в таблице есть уникальный индексированный первичный ключ
количество случайных строк, которые вы хотите выбрать (м), намного меньше, чем количество строк в таблице (n)
уникальный первичный ключ представляет собой целое число в диапазоне от 1 до n без пробелов
С учетом только предположений 1 и 2, я думаю, что это можно сделать в O (n), хотя вам нужно записать целый индекс в таблицу, чтобы соответствовать предположению 3, так что это не обязательно быстрый O (n). Если мы можем ДОПОЛНИТЕЛЬНО предположить что-то еще хорошее в отношении таблицы, мы можем выполнить задачу в O (m log m). Предположение 3 было бы хорошим приятным дополнительным свойством для работы. С хорошим генератором случайных чисел, который гарантировал отсутствие дубликатов при генерации m чисел в строке, решение O (m) было бы возможно.
Учитывая три допущения, основная идея состоит в том, чтобы сгенерировать m уникальных случайных чисел от 1 до n, а затем выбрать строки с этими ключами из таблицы. У меня сейчас нет mysql или чего-то еще, поэтому в слегка псевдокоде это будет выглядеть примерно так:
create table RandomKeys (RandomKey int)
create table RandomKeysAttempt (RandomKey int)
-- generate m random keys between 1 and n
for i = 1 to m
insert RandomKeysAttempt select rand()*n + 1
-- eliminate duplicates
insert RandomKeys select distinct RandomKey from RandomKeysAttempt
-- as long as we don't have enough, keep generating new keys,
-- with luck (and m much less than n), this won't be necessary
while count(RandomKeys) < m
NextAttempt = rand()*n + 1
if not exists (select * from RandomKeys where RandomKey = NextAttempt)
insert RandomKeys select NextAttempt
-- get our random rows
select *
from RandomKeys r
join table t ON r.RandomKey = t.UniqueKey
Если вы действительно обеспокоены эффективностью, вы можете подумать о генерации случайного ключа на каком-то процедурном языке и вставке результатов в базу данных, поскольку почти все, кроме SQL, вероятно, будет лучше в виде циклического и случайного требуется генерация номера.