1

在 ruby​​ on rails 中,所有has_many :widgets方法都生成一个object.widgets方法和一个object.widget_ids方法。

后一种方法非常有用,因为它绕过了 ActiveRecord 对象的创建并运行更快的查询。使用该选项可以提高查询速度:select,但是 ruby​​ 在生成对象而不是整数时仍然分配更多的内存。

例如

User has_many :historical_sessions:

>> Benchmark.measure { User.find(4).historical_sessions.map(&:id) }
HistoricalSession Load (131.0ms)   SELECT * FROM `historical_sessions` WHERE (`historical_sessions`.user_id = 4)
=> #<Benchmark::Tms:0xbe805c0 @cutime=0.0, @label="", @total=1.996, @stime=0.0150000000000006, @real=2.09599995613098, @utime=1.981, @cstime=0.0>
(2.1 seconds)

>> Benchmark.measure { User.find(4).historical_session_ids }
HistoricalSession Load (34.0ms)   SELECT `historical_sessions`.id FROM `historical_sessions` WHERE (`historical_sessions`.user_id = 4)
=> #<Benchmark::Tms:0x11e6cd94 @cutime=0.0, @label="", @total=1.529, @stime=0.032, @real=1.55099987983704, @utime=1.497, @cstime=0.0>
(1.6 seconds)

(结果集为 67353 个对象)

有没有办法在使用 named_scopes 时发生相同的行为?

例如,

User named_scope :recent
User.recent (Exists)
User.recent_ids (Does not exist)

我目前在命名范围结果集中获取对象 ID 的方式是:HistoricalSession.recent.map(&:id)。这与上面后一个示例中所做的基本相似,并且显然效率不高。我不想构建整个 HistoricalSession 对象,最终我只需要一个 id 数组。

另一种实现可能是新的 .find 方法。例如,HistoricalSession.recent.find_attributes(:id)。此方法将替换 select 语句以仅选择指定的值,并将缩短 ActiveRecord 对象的创建以仅返回一个数组。

有什么建议么?这可能是一个简单的插件吗?

4

3 回答 3

2

您可以在关联代理上创建一个名为“ids”的方法,而不是创建其他方法,以便您可以执行以下操作:

User.named_scope :recent, ...
User.named_scope :admin, ...
User.recent.admin.ids

是的,这对我来说听起来像是一个明智的插件。应该不会太难写。

于 2009-03-27T10:38:40.650 回答
1

由于我最初提出这个问题,Rails 在 Calculations 模块中添加了 .ids 和 .pluck 方法。这些本来可以解决我当时的问题。

采摘:https ://www.omniref.com/ruby/gems/activerecord/4.1.0/classes/ActiveRecord::Calculations##pluck

ID:https ://www.omniref.com/ruby/gems/activerecord/4.1.0/classes/ActiveRecord::Calculations##ids

于 2014-05-17T00:56:12.253 回答
0

只是在这里采取不同的观点-您为什么要为此烦恼?你用了多少内存?看起来您正在尝试优化某些东西-但如果只有几行(即少于几百行)-我不明白您为什么要为此烦恼。

你有问题,还是你想象中的问题?

不要忘记:http ://en.wikipedia.org/wiki/Program_optimization#When_to_optimize

:-D

于 2011-06-29T16:48:10.093 回答