我需要從db中選擇隨機記錄。在我用於開發的Sqlite3中,有一個名爲Random()的函數。但是,在Postgresql中,它被稱爲Rand()。我不記得MySql,但可能在那裏調用它。隨機選擇RoR中的不同數據庫
所以,如果我有一個代碼(SQLITE3)
data = Items.where(pubshied: is_pubshied).order("RANDOM()").limit(count)
我如何確保它會與不同的數據庫?
我需要從db中選擇隨機記錄。在我用於開發的Sqlite3中,有一個名爲Random()的函數。但是,在Postgresql中,它被稱爲Rand()。我不記得MySql,但可能在那裏調用它。隨機選擇RoR中的不同數據庫
所以,如果我有一個代碼(SQLITE3)
data = Items.where(pubshied: is_pubshied).order("RANDOM()").limit(count)
我如何確保它會與不同的數據庫?
Rails不支持開箱即用。我相信我有一個模型擴展(我不使用它了,因爲我強制使用PostgreSQL的),但這樣的事情可以工作,取得了這一點:
module Randomize
extend ActiveSupport::Concern
included do
scope :random, -> { order(rand_cmd) }
end
module ClassMethods
def rand_cmd
if connection.adapter_name =~ /mysql/i
'rand()'
else
'random()'
end
end
end
end
然後,您可以做
class Item
include Randomize
end
Item.where(...).random.limit(...)
性能影響是一件大事。我無法想象有人在生產中選擇這樣做。 – pguardiario
@pguardiario我不明白爲什麼有人會需要在生產中使用這個,說什麼性能影響什麼?一個方法調用? –
我的意思是像'order by rand()'那樣的性能影響,除非我弄錯了,否則每次都需要讀取完整的磁盤。 – pguardiario
從waldyr.ar在他的評論中提到的帖子的評論:https://stackoverflow.com/a/12038506/16784。
Tl; dr:您可以使用Items.all.sample(count)
。當然,這將檢索整個表格,並且可能對大型表格沒有用處。
獲取所有項目是一個糟糕的主意。 –
通過'RAND()'進行排序一般也很糟糕。這是否有用取決於預期的用途:對於小型表格,或者更可能的是,從表格中選擇較小的一種,「樣本」方法非常有用。如果表現是至關重要的,那麼就需要更精細的策略。這是一個務實的解決方案;如果有的話,我會很樂意回答如何提高績效的問題。 – Confusion
對於高性能,無適配器特定的方式隨機排序,填充隨機列,穿上它的索引並調用它是這樣的:
Foo.order("random_column > #{rand}").limit(1)
Downvoting,因爲這會給你每次相同的順序。此外,我*認爲*一旦你做減法,索引將不會被使用,所以這不利於性能。 –
是的,它應該是一個>我認爲,無論如何你明白了。 – pguardiario
有趣的,但我仍然不認爲這是一個很好的解決方案:你的'ORDER BY'子句將對某些記錄評估爲「TRUE」,對其他評估則爲'FALSE'。你總是會有越低的'random_column'值越接近開始比越高;只有這些部門之間的臨界點是隨機的。在每個分區內,排序都是不可預測的。這根本不比'ORDER BY'更好,甚至可能更糟糕,因爲它會迫使'random_column'的值更接近前端,所以隨機性會有很大偏差。 –
可能與http://stackoverflow.com/問題/ 5342270/rails-3-get-random-record –
我已經在下面添加了我的答案,但應該說你的問題是錯誤的,在sqlite3和postgresql都使用'random()'只有mysql使用'rand()' –
我對於你的問題Railsy解決方案的思考更多,但請注意,你剛剛遇到了你應該使用相同的數據庫系統進行開發和生產的原因。在本地安裝Postgres進行開發;這很值得。 –