jla*_*rcy 5 mysql database time-series
我想将时间序列存储在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);
Run Code Online (Sandbox Code Playgroud)
提供了度量和站点表,如果我的主要查询是:
SELECT *
FROM TimeSeries
WHERE (MeasureId IN (?,?,?))
AND (SiteId IN (?,?,?))
AND (MeasureTimeStamp BETWEEN ? AND ?)
ORDER BY MeasureId ASC,
SiteId ASC,
MeasureTimeStamp ASC;
Run Code Online (Sandbox Code Playgroud)
编辑2:
站点大约20个,度量大约为50.这导致最多1000个通道(站点和度量对).它可能会在几十年内增加一点点,但不会超过10000个频道.大多数数据的时间粒度约为30分钟.无论如何,粒度不是恒定的,并且不会小于一分钟(一些数据是每天或每周).
一些线索:
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 可以使用您的索引或唯一约束。这取决于它选择的表中的数据。然而,这两者都不是最佳的。使用索引,它将快速找到索引中具有正确的MeasureId
和 的块SiteId
,但随后需要进入主表中的每个值来检查 是否MeasureTimeStamp
在范围内。使用唯一约束可以轻松选择时间范围。然而,该索引子集具有MeasureId
随机SiteId
排序,仍按 MeasureTimeStamp 排序。
为了改善你的结构,它将有助于改变你的独特约束
约束唯一(MeasureId、SiteId、MeasureTimeStamp)
该索引现在将按照我希望显示更好性能的值进行排序12_68_2014-12-23 09:01:43
,因为 MySQL 现在可以在索引中选择离散且可预测的范围数。这覆盖了您的 SELECT 语句,同时使您的索引变得多余。