【问题标题】:Timeserie database linear storage时序数据库线性存储
【发布时间】:2015-01-05 01:55:17
【问题描述】:

我想将时间序列存储在 MySQL 数据库中。我想以线性方式进行,也就是说,每一行都代表一个独特的观察结果(1 个度量,1 个站点,1 个时间戳)。目前,它将需要84 096 000 行,并且每年将增长约2 102 400 行。

为了正确设计时间序列表、索引和相关查询(本质上是确定度量、站点和时间范围的数据选择),必须采取哪些预防措施。

编辑:

增加表格设计提案:

CREATE TABLE TimeSeries(
   Id                  INT          NOT NULL     AUTO_INCREMENT,
   MeasureTimeStamp    DATETIME     NOT NULL, 
   MeasureId           INT          NOT NULL,
   SiteId              INT          NOT NULL,
   Measure             FLOAT        NOT NULL,
   Quality             INT          NOT NULL,   
   PRIMARY KEY (Id),
   CONSTRAINT UNIQUE (MeasureTimeStamp,MeasureId,SiteId),
   FOREIGN KEY (MeasureId) REFERENCES Measure(Id),
   FOREIGN KEY (SiteId) REFERENCES Site(Id)
);
CREATE INDEX ChannelIndex ON TimeSeries(MeasureId,SiteId);

如果存在 Measure 和 Site 表,如果我的主要查询是:

SELECT *
FROM TimeSeries
WHERE (MeasureId IN (?,?,?)) 
  AND (SiteId IN (?,?,?))
  AND (MeasureTimeStamp BETWEEN ? AND ?)
ORDER BY MeasureId ASC,
         SiteId ASC,
         MeasureTimeStamp ASC;

编辑 2:

站点大约有 20 个,度量大约有 50 个。这导致最多 1000 个通道(站点和度量对)。它可能会在几十年内增加一点,但不会超过 10000 个频道。大多数数据的时间粒度约为 30 分钟。无论如何时间粒度不是恒定的,不会小于一分钟(有些数据是每天或每周)。

【问题讨论】:

  • MySQL 可以轻松搞定。你预计会有什么样的 WHERE 子句?最低限度,“网站”的索引。
  • WHERE 子句将至少选择两个外键 sitemeasure 使用 IN 列表标准(这些列当然会被索引)和 timestamp 使用 @ 987654330@(索引,因为它是主键的一部分)。
  • 那么我建议同时使用sitemeasure 创建一个索引。这两列将减少结果以提高效率。如果您将 Timestamp 添加到组合中,那么您的索引将拥有与数据表一样多的行,而 MySQL 将忽略它。
  • 您的年度增长与您每秒的实际写入操作数(可能包括 FK)相比,并没有那么重要。你能多谈谈数据的“密度”吗……有 5 个站点吗?还是50000?有多少措施?是每秒记录 TS,每秒 10 次吗?等
  • @cerd 增加了 FK 密度的精度

标签: mysql database time-series


【解决方案1】:

一些线索:

  • MySQL 中的索引是按“索引列”排序的主键列表。您希望对该列表进行排序,以便尽可能容易地找到所需的值。
  • MySQL 一次只在一个表上使用一个索引。
  • MySQL 可以使用从左到右的索引(MySQl Multi-column indexes)。这意味着 Index(A,B,C) 允许您执行 WHERE A=? AND B=? 而不是 WHERE B=? AND C=?

在您的示例中,创建了四个索引:

  • MeasureId,SiteId(频道索引)
  • MeasureTimeStamp,MeasureId,SiteId(唯一约束)
  • MeasureId(外键)
  • SiteId(外键)

简单地说,ChannelIndex 的排序就像一个组合 MeasureId 和 SiteId 的字符串列表。例如。对于 MeasureId = 12 和 Site Id = 68,您可以将排序值想象为 12_68。 您的唯一约束根据2014-12-23 09:01:43_12_68 等值进行排序。

为了解决您的查询,MySQL 可以使用您的索引或唯一约束。这取决于它选择的表中的数据。然而,两者都不是最优的。使用索引,它会在索引中快速找到具有正确MeasureIdSiteId 的块,但随后需要进入主表中的每个值以检查MeasureTimeStamp 是否在范围内。 使用唯一约束可以轻松选择时间范围。但是,此索引子集具有随机排序的 MeasureIdSiteId,仍按 MeasureTimeStamp 排序。

为了改善您的结构,将您的唯一约束更改为

约束唯一性(MeasureId、SiteId、MeasureTimeStamp)

该索引现在将使用 12_68_2014-12-23 09:01:43 之类的值进行排序,因为 MySQL 现在可以在索引中选择离散且可预测的范围数量,因此我希望显示更好的性能。这涵盖了您的 SELECT 语句,同时使您的索引变得多余。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    • 1970-01-01
    • 2012-09-02
    • 2011-05-09
    • 2012-12-16
    • 1970-01-01
    • 2022-11-15
    相关资源
    最近更新 更多