很多人提到了
.pluck
。它确实有一个警告,它返回找到记录的列的数组。
如果列是唯一的,比如
id
,那就不是问题,DB会向Active Record发送相同内容,1个记录1个列,使用
limit(1)
或不使用(使用它是无用的,并且很可能会被DB查询优化器丢弃)。
但是,如果列不是唯一的,它实际上可能不是最佳性能。因为,在AR执行DB查询后,
first
被调用,返回从DB带来的所有结果的
[0]
。
limit
在此之前被调用,并作为查询的一部分发送给DB,过滤结果。
考虑以下表格和设置:
> Log
=> Log(id: integer, user_id, integer, event_type: integer, timestamp: datetime)
> user_newest_logs = Log.where(user_id: 1).order(timestamp: :desc)
现在,让我们获取user_id = 1的最后事件日期时间:
1)这是最好的方法。数据库返回一个带有时间戳列的记录。
Original Answer: 最初的回答
> user_newest_logs.limit(1).pluck(:timestamp).first
SELECT timestamp FROM logs WHERE logs.user_id = 1 ORDER BY logs.timestamp DESC LIMIT 1
=> Fri, 09 Aug 2019 23:00:00 UTC +00:00
2) 数据库返回一条记录,包括所有列
最初的回答
> user_newest_logs.first
SELECT * FROM logs WHERE logs.user_id = 1 ORDER BY logs.timestamp DESC LIMIT 1
=> #<Log:0x00111111>
id: 920821839,
user_id: 1,
event_type: 1,
timestamp: Fri, 09 Aug 2019 23:00:00 UTC +00:00
> user_newest_logs.first.timestamp
SELECT * FROM logs WHERE logs.user_id = 1 ORDER BY logs.timestamp DESC LIMIT 1
=> Fri, 09 Aug 2019 23:00:00 UTC +00:00
3) 数据库返回N条记录的时间戳列表
注:Original Answer翻译成“最初的回答”
> user_newest_logs.pluck(:timestamp)
SELECT timestamp FROM logs WHERE logs.user_id = 1 ORDER BY logs.timestamp DESC
=> [Fri, 09 Aug 2019 23:00:00 UTC +00:00,
Fri, 09 Aug 2019 22:00:00 UTC +00:00,
Fri, 09 Aug 2019 21:00:00 UTC +00:00,
Fri, 09 Aug 2019 20:00:00 UTC +00:00,
...
]
> user_newest_logs.pluck(:timestamp).first
SELECT timestamp FROM logs WHERE logs.user_id = 1 ORDER BY logs.timestamp DESC
=> Fri, 09 Aug 2019 23:00:00 UTC +00:00
> user_newest_logs.pluck(:timestamp).count
=> 1523
因此,如果你使用pluck(:column).first
,实际上比仅使用find_by.column
更糟。
"最初的回答"
user_name = User.select("user_name").where(user_id).first
时会发生什么? - ScottJSheapick(:id)
,它类似于pluck(:id).first
。 - Kris