Итак, я нашел несколько примеров поиска случайной записи в Rails 2 - кажется, предпочтительный метод:
Thing.find :first, :offset => rand(Thing.count)
Будучи новичком, я не уверен, как это можно построить с использованием нового синтаксиса find в Rails 3.
Итак, что же такое «Rails 3 Way» для поиска случайной записи?
Ответы:
или
Собственно, в Rails 3 все примеры будут работать. Но использование порядка
RANDOM
довольно медленно для больших таблиц, но больше в стиле sqlUPD. Вы можете использовать следующий трюк с индексированным столбцом (синтаксис PostgreSQL):
источник
RAND()
илиRANDOM()
. СпасибоЯ работаю над проектом ( Rails 3.0.15, ruby 1.9.3-p125-perf ), где база данных находится в локальном хосте, а таблица пользователей имеет немного более 100 КБ записей .
С помощью
довольно медленно
становится
и на ответ требуется от 8 до 12 секунд !!
Журнал Rails:
из mysql объяснить
Вы можете видеть, что индекс не используется ( possible_keys = NULL ), создается временная таблица и требуется дополнительный проход для извлечения желаемого значения ( extra = Использование временного; Использование файловой сортировки ).
С другой стороны, разделив запрос на две части и используя Ruby, мы получаем разумное улучшение времени отклика.
(; nil для использования в консоли)
Журнал Rails:
и mysql объясняет, почему:
теперь мы можем использовать только индексы и первичный ключ и выполнять работу примерно в 500 раз быстрее!
ОБНОВИТЬ:
как указано icantbecool в комментариях, вышеупомянутое решение имеет недостаток, если в таблице есть удаленные записи.
Обходной путь в этом может быть
что означает два запроса
и работает примерно за 500 мс.
источник
RAND(id)
будет задавать разный случайный порядок для каждого запроса. Используйте,RAND()
если хотите, чтобы каждый запрос был в другом порядке.Если вы используете Postgres
При использовании MySQL
В обоих случаях вы случайным образом выбираете 5 записей из таблицы Users. Вот фактический запрос SQL, отображаемый в консоли.
источник
Для этого я сделал жемчужину rails 3, которая лучше работает с большими таблицами и позволяет связывать отношения и области:
https://github.com/spilliton/randumb
(править): поведение моего драгоценного камня по умолчанию в основном использует тот же подход, что и выше, но у вас есть возможность использовать старый способ, если хотите :)
источник
Многие из опубликованных ответов на самом деле не будут работать с довольно большими таблицами (более 1 миллиона строк). Произвольный порядок быстро занимает несколько секунд, и подсчет по таблице также занимает довольно много времени.
Решение, которое хорошо работает для меня в этой ситуации, заключается в использовании
RANDOM()
условия where:Для таблицы, содержащей более миллиона строк, этот запрос обычно занимает менее 2 мс.
источник
take
функции, которая выдаетLIMIT(1)
запрос, но возвращает один элемент вместо массива. Так что ссылаться не нужноfirst
вот так
рельсы путь
использование
или вторая мысль
использование:
источник
Couldn't find all Users with 'id': (first, {:offset=>1}) (found 0 results, but was looking for 2)
"RANDOM()"
вместо этого ...Это было очень полезно для меня, но мне нужно было немного больше гибкости, поэтому я сделал следующее:
Случай 1: поиск одного случайного источника записи : сайт trevor
turk Добавьте это в модель Thing.rb
тогда в вашем контроллере вы можете вызвать что-то вроде этого
Случай 2: поиск нескольких случайных записей (без повторов). Источник: не могу вспомнить,
мне нужно было найти 10 случайных записей без повторов, так что это то, что я нашел, работало
В вашем контроллере:
Будет найдено 10 случайных записей, однако стоит упомянуть, что если база данных особенно велика (миллионы записей), это будет не идеально, и производительность будет снижена. Is будет работать до нескольких тысяч записей, чего мне было достаточно.
источник
Метод рубина для случайного выбора элемента из списка
sample
. Желая создать эффективныйsample
для ActiveRecord и основываясь на предыдущих ответах, я использовал:Я вставляю это
lib/ext/sample.rb
и затем загружаю это с этимconfig/initializers/monkey_patches.rb
:источник
#count
вызовет БД для файлаCOUNT
. Если запись уже загружена, это может быть плохой идеей.#size
Вместо этого можно было бы использовать рефакторинг, поскольку он решит,#count
следует ли его использовать или, если запись уже загружена, использовать#length
.count
наsize
на основе вашего отзыва. Дополнительная информация: dev.mensfeld.pl/2014/09/…Работает в Rails 5 и не зависит от БД:
Это в вашем контроллере:
Вы, конечно, можете указать на это, как показано здесь .
приложение / модель / проблемы / randomable.rb
затем...
приложение / модели / book.rb
Тогда вы можете просто использовать:
или
источник
Вы можете использовать sample () в ActiveRecord
Например
Источник: http://thinkingeek.com/2011/07/04/easily-select-random-records-rails/
источник
sample
отсутствует в ActiveRecord, образец находится в массиве. api.rubyonrails.org/classes/Array.html#method-i-sampleПри использовании Oracle
Вывод
источник
Настоятельно рекомендую этот гем для случайных записей, который специально разработан для таблиц с большим количеством строк данных:
https://github.com/haopingfan/quick_random_records
Все остальные ответы плохо работают с большой базой данных, кроме этого драгоценного камня:
4.6ms
полностью.User.order('RAND()').limit(10)
стоимость принятого ответа733.0ms
.offset
подход стоит245.4ms
полностью.User.all.sample(10)
затратный подход573.4ms
.Примечание: в моей таблице всего 120 000 пользователей. Чем больше у вас записей, тем значительнее будет разница в производительности.
ОБНОВИТЬ:
Выполнить на таблице с 550 000 строками
Model.where(id: Model.pluck(:id).sample(10))
Стоимость1384.0ms
gem: quick_random_records
только стоимость6.4ms
полностьюисточник
Очень простой способ получить несколько случайных записей из таблицы. Это делает 2 дешевых запроса.
Model.where(id: Model.pluck(:id).sample(3))
Вы можете изменить цифру «3» на нужное количество случайных записей.
источник
Я только что столкнулся с этой проблемой при разработке небольшого приложения, в котором я хотел выбрать случайный вопрос из моей БД. Я использовал:
И это хорошо работает для меня. Я не могу говорить о производительности для больших БД, поскольку это всего лишь небольшое приложение.
источник
shuffle[0]
)