Postgresql ActiveRecordfirst方法是否总是返回ID最小的记录?
环境:Rails 4.2.4,Postgres 9.4.1.0 是否可以保证ActiveRecordfirst方法将始终返回ID最小的记录和ID最大的ActiveRecordlast 我可以从Rails控制台看到,对于这两种方法,适当的顺序ASC/DESC被添加到生成的SQL中。但另一个SO线程的作者告诉我们,第一个方法返回的不是第一条记录 ActiveRecord优先: 2.2.3:001>账户优先 帐户加载1.3ms选择帐户。*从帐户顺序按帐户。id ASC限制1 ActiveRecord上次: 2.2.3:002>Account.last 帐户加载0.8ms选择帐户。*从帐户按帐户排序。id描述限制1 ========== 稍后添加: 所以,我根据D-side的答案做了自己的调查,答案是否定的。一般来说,唯一的保证是第一个方法将返回集合中的第一条记录。它可能会产生副作用,将ORDER BY PRIMARY_KEY条件添加到SQL中,但这取决于记录是否已加载到缓存/内存中 以下是从Rails 4.2.4中提取的方法: /activerecord/lib/active\u record/relation/finder\u methods.rb 现在,示例与有很多关系: Account有多个AccountStatus,AccountStatus属于AccountPostgresql ActiveRecordfirst方法是否总是返回ID最小的记录?,postgresql,ruby-on-rails-4,activerecord,Postgresql,Ruby On Rails 4,Activerecord,环境:Rails 4.2.4,Postgres 9.4.1.0 是否可以保证ActiveRecordfirst方法将始终返回ID最小的记录和ID最大的ActiveRecordlast 我可以从Rails控制台看到,对于这两种方法,适当的顺序ASC/DESC被添加到生成的SQL中。但另一个SO线程的作者告诉我们,第一个方法返回的不是第一条记录 ActiveRecord优先: 2.2.3:001>账户优先 帐户加载1.3ms选择帐户。*从帐户顺序按帐户。id ASC限制1 ActiveRecord上
a = Account.first
a.account_statuses # No ordering
a.account_statuses.first
# Here is a tricky part: sometimes it returns @record[index] entry, sometimes it may add ORDER BY ID (if records were not loaded before)
以下是我的结论:
将方法first视为从已加载的集合返回第一条记录,该集合可以按任意顺序加载,即无序加载。若我想确保第一个方法将返回ID最小的记录,那个么我应用第一个方法的集合应该在之前进行适当的排序
关于第一种方法的Rails文档是错误的,需要重写。
1.1.3首先
第一个方法查找按主键排序的第一条记录 我认为您引用的答案甚至与它所涉及的问题都不相关,因为它指的是非有序查询,而第一个和最后一个确实应用了基于id的顺序 在某些情况下,如果要对查询应用自己的组,则不能使用first或last,因为如果分组不包含id,则无法应用order by,但可以使用take来只返回第一行
我记得,有一些版本的first和/或last没有在PostgreSQL上应用最新Rails 3的顺序1,但它们都是错误的。它可能会根据您的数据库引擎而变化,它总是使用first方法返回mysql中的最小ID,但对PostgreSQL不起作用,当我还是nobai的时候,我有几个问题,我的应用程序在本地mysql中正常工作,但是当使用postgresql部署到heroku时,一切都乱七八糟,因此为了避免postgresql出现问题,请在查询之前始终按id排序记录:
SELECT `accounts`.* FROM `accounts` ORDER BY `accounts`.`id` ASC LIMIT 1
帐户。订单:id优先
以上确保了mysql、postgresql和任何其他数据库引擎的最小ID,如查询中所示:
SELECT `accounts`.* FROM `accounts` ORDER BY `accounts`.`id` ASC LIMIT 1
如果未选择排序,则将以未指定的方式返回行
顺序这种情况下的实际顺序将取决于扫描和连接
计划类型和磁盘上的顺序,但不能依赖它。A.
只有在执行排序步骤时,才能保证特定的输出顺序
明确选择
重点矿山
所以ActiveRecord实际上增加了主键排序,以保持结果的确定性。相关的源代码很容易找到,但以下是Rails 4.2.4的摘录:
# show-source Thing.all.first
def first(limit = nil)
if limit
find_nth_with_limit(offset_index, limit)
else
find_nth(0, offset_index)
end
end
# show-source Thing.all.find_nth
def find_nth(index, offset)
if loaded?
@records[index]
else
offset += index
@offsets[offset] ||= find_nth_with_limit(offset, 1).first
end
end
# show-source Thing.all.find_nth_with_limit
def find_nth_with_limit(offset, limit)
relation = if order_values.empty? && primary_key
order(arel_table[primary_key].asc) # <-- ATTENTION
else
self
end
relation = relation.offset(offset) unless offset.zero?
relation.limit(limit).to_a
end
所以,相信first会返回ID最低、ID最高的记录安全吗?high是指last,但是的。
# show-source Thing.all.first
def first(limit = nil)
if limit
find_nth_with_limit(offset_index, limit)
else
find_nth(0, offset_index)
end
end
# show-source Thing.all.find_nth
def find_nth(index, offset)
if loaded?
@records[index]
else
offset += index
@offsets[offset] ||= find_nth_with_limit(offset, 1).first
end
end
# show-source Thing.all.find_nth_with_limit
def find_nth_with_limit(offset, limit)
relation = if order_values.empty? && primary_key
order(arel_table[primary_key].asc) # <-- ATTENTION
else
self
end
relation = relation.offset(offset) unless offset.zero?
relation.limit(limit).to_a
end