我有一个包含一堆deviceapi条目的数据库,它们有一个start_date和end_date(模式中的datetime)。通常这些条目的长度不超过20秒(end_date - start_date)。我有以下设置:
data = Deviceapi.all.where("start_date > ?", DateTime.now - 2.weeks)
我需要获得具有最高数量的Deviceapi条目的数据。为了使它更清晰一点,这是我最近的尝试(代码近似,不介意错别字):
runningtotal = 0
(2.weeks / 1.hour).to_i.times do |interval|
current = data.select{ |d| d.start_time > (start_date + (1.hour * (interval - 1))) }.select{ |d| d.end_time < (start_date + (1.hour * interval)) }.count
if current > runningtotal
runningtotal = current
end
问题:这段代码运行得很好。关于它的十几个其他化身,使用.where,.select,SQL查询等也是如此。但它太慢了。 Waaaaay太慢了。因为它必须在2周内每小时循环一次。那么这个方法可能需要自己调用几十次。
必须有更快的方法来做到这一点,也许是一种?我很难过,而且我一直在寻找没有运气的好几个小时。有什么想法吗?
答案 0 :(得分:1)
为了获得足够的性能,您需要在单个查询中执行所有操作,这意味着要避免 ActiveRecord 功能并执行原始查询(例如,通过{{ 1}})。
我无法测试它,因为我既没有您的数据也没有架构,但我认为这些内容可以满足您的需求:
For Each result In query
Msgbox(result.TABLENAME & "." & result.COLUMNNAME)
Next
从最内层的查询出来的逻辑如下:
如果恰好有多个条目具有相同数量的条目,您可以确定一致的方式来选择一个 - 比如ActiveRecord::Base.connection.execute
或类似(因为即使数据得到,它也会保持不变添加,假设您没有删除项目。)
如果您想限制初始时间片 - 我发现您的帖子中提到了2周 - 您可以在最里面的查询中执行此操作,并使用select y.starting_hour, max(y.num_entries) as max_entries
from
(
select x.starting_hour, count(*) as num_entries
from
(
select date_trunc('hour', start_time) starting_hour
from deviceapi as d
) as x
group by x.starting_hour
) as y
where y.num_entries = max(y.num_entries);
子句将日期范围括起来。