Как сделать эффективную простую случайную выборку в SQL? В этой базе данных работает MySQL; моя таблица составляет не менее 200 000 строк, и я хочу, чтобы простая случайная выборка составляла около 10 000.
"Очевидный" ответ:
SELECT * FROM table ORDER BY RAND() LIMIT 10000
Для больших таблиц это слишком медленно: он вызывает RAND() для каждой строки (которая уже помещает ее в O (n)) и сортирует их, делая в лучшем случае O (n lg n). Есть ли способ сделать это быстрее, чем O (n)?
Примечание. Как отмечает Эндрю Мао в комментариях. Если вы используете этот подход на SQL Server, вам следует использовать функцию NEWID(), поскольку RAND() может возвращать одинаковое значение для всех строк.
ИЗМЕНИТЬ: 5 ЛЕТ ПОЗЖЕ
Я снова столкнулся с этой проблемой с большим столом и в итоге использовал версию решения @ignorant с двумя настройками:
- Попробуйте строки для 2-5x желаемого размера выборки, чтобы дешево ORDER BY RAND()
- Сохраните результат RAND() в индексированном столбце при каждой вставке/обновлении. (Если ваш набор данных не очень тяжелый, вам может понадобиться другой способ сохранить этот столбец свежим.)
Чтобы взять образец таблицы из 1000 элементов, я подсчитываю строки и просуммировал результат до, в среднем, 10 000 строк с столбцом frozen_rand:
SELECT COUNT(*) FROM table; -- Use this to determine rand_low and rand_high
SELECT *
FROM table
WHERE frozen_rand BETWEEN %(rand_low)s AND %(rand_high)s
ORDER BY RAND() LIMIT 1000
(Моя фактическая реализация включает в себя больше работы, чтобы убедиться, что я не делаю этого, и вручную обернуть rand_high, но основная идея - "случайным образом сократить ваш N до нескольких тысяч".)
В то время как это приносит некоторые жертвы, это позволяет мне пробовать базу данных вниз с помощью сканирования индекса, пока она не станет достаточно маленькой для ORDER BY RAND().