savostin
@savostin
Еще один программист

Существует ли «база данных», в которой бы можно было сделать выборку N случайных записей из отфильтрованного по условиям набора?

Подскажите пожалуйста существует ли "база данных", в которой бы можно было сделать выборку N случайных записей из отфильтрованного по условиям набора?
Псевдокод:
SELECT id, name, param1, param2 
FROM table 
WHERE param1 = some_value 
AND param2 > another_one 
ORDER BY RANDOM() 
LIMIT @N

MySQL, да и, наверное, другие популярные базы, от такого запроса умирают, естественно.
Всякие обходные костыли, типа дополнительное поле с рандомом, перемешивать по крону, составлять запросы на лету и процедуры и пр. не совсем подходят - нужно действительно при каждом запросе отдавать рандомные строки, N > 10000, id с дырами, объемы большие. Может быть есть что-то специализированное? Не обязательно SQL. Может даже сервис, хоть и не желательно.
  • Вопрос задан
  • 3124 просмотра
Пригласить эксперта
Ответы на вопрос 6
Kerman
@Kerman
Если нужен именно честный выбор действительно случайных и равномерно распределённых 10000 строк из пятимиллионной таблицы, то лучше SQL с этой задачей ничто не справится. Разве что самописная база, заточенная конкретно под этот случай. Нужно просто расставить индексы на нужные поля, чтобы облегчить поиск.
Мой совет: добавьте памяти на сервер, проиндексируйте поля. Всё будет хорошо, используйте стандарный RAND(), оптимизировав его до приемлемого значения.

Для редких случаев ещё помогает выборка массива ID по условию и дальнейший выбор нужного количества случайных ID из массива.
Ответ написан
Комментировать
Keksinautin
@Keksinautin
Software Engineer
А почему нельзя просто сначала сделать выборку (отфильтровать по условию), а потом из нее, выбрать сколько нужно случайных по порядку записей?

Может быть еще вот эта статья будет полезна akinas.com/pages/en/blog/mysql_random_row
Ответ написан
egor_nullptr
@egor_nullptr
Смотрите в сторону MongoDB и MapReduce.
Ответ написан
@zvorygin
Тогда, мне кажется, самое простое, быстрое и правильное решение - написать свое приложение (или сервис, если так удобнее), которое будет хранить все эти данные в сыром файле и за один проход выдавать нужный список. Тогда можно будет выполнять такие запросы "относительно быстро" - меньше чем за одну минуту, причем в независимости от того, сколько одновременно запросов будет выполняться.

Причем выборка будет максимально честной. А вообще - можно взять на вооружение как интересную задачку для интервью)
Ответ написан
@zvorygin
Тогда, если учесть, что запросы могут быть какими угодно, вам надо будет на каждый запрос читать всю таблицу хотя бы для того чтобы отфильтровать(хоть самописное у вас, хоть oracle, хоть mysql) - т.е. читать 5Гб (это самый медленный момент во всей системе). Если взять скорость последовательного чтения(а случайное чтени + SSD вам не помогут, как мне кажется), то время чтения будет порядка 5Гб/150МБс т.е. около 30 секунд. Если предположить что записи меняются редко, то можно все это дело дополнительно сжать(зависит от реальных данных) - хранить записи не фиксированной длины - возможно еще процентов 15(или больше) экономии выжмется - итого 25 секунд. Можно применить RAID и ускорить еще в пару раз(или в большее - в зависимости от реализации) - итого получаем 15 секунд на запрос. Никакие стандартные кеши при последовательном чтении не помогут, но можно попробовать просто забить всю свободную память кусками данных - и к ним обращаться не с диска - это дает еще 2Гб в памяти и, на вскидку экономию в 30-40 процентов. Итого, мне кажется, 10 секунд - довольно хороший гарантированный и достижимый результат на почти любых фильтрах и запросах. Если есть заранее известные данные о фильтрации, то можно пробовать как-то по-другому оптимизировать.
Ответ написан
@Aisu
Я не знаю как это сделать в MySQL однако решала такую задачу в sql server . Так вот идея такая - добавляется дополнительное поле в запрос в котором вычисляется функция уникального номера, а в ордере указывается это поле, несмотря на ваши условия выборки. Далее выставите top 10000. Вот и все. Правда не знаю насколько он быстро выполниться, хотя думаю 10000 строк это не много для запроса в SQL Server...
Пример
SELECT TOP 10000 [StudentKID]
,[SKPersRecN]
,[SKSurname]
,[SKName]
,[SKSecondName]
,[FacultyID], NewId() as t
FROM [StudentsKredit]
where FacultyID='ИУБ'
order by t
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы