Ruby on rails 如何加速这些ActiveRecord查询?
我的数据库中有三个表:值、键和源。键和源都有许多值。sources有一个名为file\u date的datetime列。对于每个键,我必须选择源在特定日期范围(通常在两年内)之间的所有值。并非该范围内的所有日期都有来源,也并非所有来源都有值。我需要创建一个数组,其中包含该范围内的所有值 起初,我尝试一次简单地查询整个源数组,如下所示:Ruby on rails 如何加速这些ActiveRecord查询?,ruby-on-rails,rails-activerecord,Ruby On Rails,Rails Activerecord,我的数据库中有三个表:值、键和源。键和源都有许多值。sources有一个名为file\u date的datetime列。对于每个键,我必须选择源在特定日期范围(通常在两年内)之间的所有值。并非该范围内的所有日期都有来源,也并非所有来源都有值。我需要创建一个数组,其中包含该范围内的所有值 起初,我尝试一次简单地查询整个源数组,如下所示: Value.where(key: 1, source: sources_array) 但是,由于有几个值为零,因此它只返回在该日期具有值的记录 现在,我创建了一
Value.where(key: 1, source: sources_array)
但是,由于有几个值为零,因此它只返回在该日期具有值的记录
现在,我创建了一个数组,其中包含该日期范围内的所有源。没有来源的日子只有零。然后,对于每个键,我遍历sources数组,返回与foo和source匹配的值。这显然是不理想的,页面加载大约需要7秒钟
这是代码:
sources.map do |source|
Value.where(source: source, key: key)
end
有什么想法吗 您的
.map
的一个大问题是,它运行多个查询,而不是一个包含所有所需结果的查询。对于每个额外的查询,您都会增加将请求发送到数据库和接收响应的开销。您需要做的是以一种返回您可能要查找的所有结果的方式生成查询,然后处理任何分组或排序应用程序端 您可以尝试在单个事务中包装查询:
ActiveRecord::Base.transaction do
sources.map do |source|
Value.where(source: source, key: key)
end
end
我需要疯狂地重构它,但我有一些东西把它缩短到了3秒:
source_ids = sources.map do |source|
if source
source.id
else
nil
end
end
values = Value.where(source: sources, key: key)
value_sources = values.pluck(:source_id)
value_decimals = values.pluck(:value_decimal)
source_ids.map do |id|
index = value_sources.index(id)
if index
value_decimals[index]
else
nil
end
end
如果只需要检索数据,并且获取数组就足够了,那么还可以生成一个SQL查询
output = []
sources.each do |source|
output << "select * from values where (source like #{source} and key like #{key})"
end
result = ActiveRecord::Base.connection.execute(output.join(" union ")).to_a
output=[]
sources.each do|source|
我已经试过了。我找不到任何东西,如果ActiveRecord找不到任何东西,它将返回nil。如果它找不到任何东西,它应该返回一个与空数组等效的对象。您可以调用.to_a
获取数组,也可以调用.empty?
在没有结果时返回true有结果,但源数组的某些值为零(因为那天没有源)。ActiveRecord只是忽略数组中的nil值。另外,那天还有一些源没有该键的值。我刚刚尝试过,但它仍然在7秒时计时。我得到了以下错误:ActiveRecord::StatementInvalid:PG::SyntaxError:error:内存在“源”或“源”附近耗尽
您可以尝试将“联合”更改为“联合所有”,关于这个SE问题:这似乎是PostgreSQL中组合多个select查询的常用方法。