ruby-on-rails - 使用 postgresql 和 ruby​​ on rails 优化时间序列数据检索的数据库查询

标签 ruby-on-rails ruby postgresql query-optimization timeoutexception

大家好,我正在开发一个有趣的实时应用程序。 应用如下。我有一个meter模型和一个meter_info模型

calss Meter
  has_many :meter_infos
  # filed: id 
end

class MeterInfo
  belongs_to :meter
  # field: meter_id, voltage 
end

每两分钟就有一个新数据被保存到meter_info表中。所以你可以想象那里有一个巨大的数据集。

现在我要做的是在 1 天内以 10 分钟为间隔,每次准确地找出一条 10 的电压记录。 所以结果会是这样的

id           created_at          meter_id      voltage
2001     2017-10-19 15:40:00        2             100
2001     2017-10-19 15:45:00        1             100
2001     2017-10-19 15:39:00        3             100
2001     2017-10-19 15:48:00        4             100
2001     2017-10-19 15:38:00        5             100
2001     2017-10-19 15:42:00        6             100
...
...

我已经尝试了几个查询,但由于查找记录需要花费太多时间,因此请求超时。这是我尝试过的

(('2017-07-02 00:00:00').to_datetime.to_i .. 
  ('2017-07-02 23:59:59').to_datetime.to_i).step(10.minutes) do |date|
                query = "SELECT  created_at, meter_id, voltage
                FROM meter_infos
                WHERE created_at between  '#{Time.at(date).utc}' and 
                '#{Time.at(date).utc + 10.minutes}'
                AND meter_id in (1,2,3,4,5)
                ORDER BY id desc limit 1"

                voltages = ActiveRecord::Base.connection.execute(query)

end

即使在开发环境中也会超时。 然后我尝试使用 Postgresqlgenerated_series 如下所示

  query= "SELECT meter_id,voltage,  count(id) as ids
              , GENERATE_SERIES( timestamp without time zone '2017-10-19',
                  timestamp without time zone '2017-10-19',
                 '10 min') as time_range
              from meter_infos
              where meter_infos.created_at between '2017-10-19 00:00:01'::timestamp and  '2017-10-19 23:59:59'::timestamp
              and meter_infos.meter_id in (1,2,3,4,5)
                  GROUP BY meter_id, voltage
              ORDER BY meter_id ASC limit 1"

            sbps_plot = ActiveRecord::Base.connection.execute(query)

哪个更快但给我错误的数据。 我正在使用 Ruby on RailsPostgresql。 有人可以帮我编写更快的查询来找出时间数据,或者建议我处理时间序列数据分析的任何程序。 提前致谢。

最佳答案

您每两分钟就有一次记录,但您希望以十分钟为间隔获取样本记录。这是我建议的解决方案:

您可以将 created_at 时间戳的纪元时间取模 600(十分钟以秒为单位)。然后将其与某些“容差”值(例如 119 秒或更短)进行比较,以防您的记录的时间戳与完美的十分钟间隔对齐。想一想在一天中每隔 10 分钟后的 2 分钟窗口内检索带有 created_at 的第一条记录。

例如,

MeterInfo
  .where(
    meter_id: [1, 2, 3, 4, 5], 
    created_at: your_date.beginning_of_day..your_date.end_of_day
  )
  .where("(cast(extract(epoch from created_at) as integer) % 600) < 119")

试一试,看看它是否适合你。

关于ruby-on-rails - 使用 postgresql 和 ruby​​ on rails 优化时间序列数据检索的数据库查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46829457/

相关文章:

ruby-on-rails - rails 3 : Link_to list item?

mysql - 预加载 Rails 4 - 仍然有多个查询

ruby-on-rails - 模型未保存时在客户端获取错误文本

ruby-on-rails - Rails 复杂 if

sql - 如何获取一列中具有最大值的行?

jquery - 在 Bootstrap 模态之间切换

ruby-on-rails - 无法在 Rails 邮件 View 中生成删除链接

ruby-on-rails - rails : Creating new Ruby on Rails app in existing directory

sql - 如何在 PostgreSQL 中的连接中使用 Case 语句?

mysql - SQL 以独立于数据库的方式填充零(LPAD)