【发布时间】:2016-06-02 13:46:20
【问题描述】:
我的情况有点难以解释,但我会努力的。
比如说,我有 50 米,每个米每分钟输出一些值,我目前已经建立了一个表格,这样每分钟就有 50 行添加到每个米的表格中,如下所示:
每分钟 50 行这样:
id, datetime, meternumber, metervalue
然后我有另一个表:
id, meternumber, metername
这样我就可以加入每个仪表编号的仪表名称。基本的东西。
但是,这很快就会成为一个问题,因为每分钟 50 行是一个巨大的行数。我还必须对仪表值进行一些平均和求和,这并不容易也不是有效的,因为当我必须对 50 行中的每一行的每 50 行求和时,求和和平均值似乎不能很好地工作,因为我想对每个仪表的仪表值求和/平均。
所以我在想,我是否应该像这样制作 50 列:
id, datetime, meter_1_value, meter_2_value, ..., meter_n_value
这基本上将行数除以 50 并使求和变得容易得多,因为现在我可以对每一行求和:
id, datetime, meter_1_value_summed, meter_2_value_summed, ..., meter_n_value_summed
那么基本上将这 50 行转换为表格的列是个好主意吗?我还尝试在查询时执行此操作,首先创建一个将行转换为列的临时表,然后查询该表,但由于已经有 1500 万行,它变得越来越慢。
索引、分区和增加服务器规格并没有多大作用,所以我开始没有想法了。
我知道你们出于某种原因想查看实际的表格数据,所以这里是一个示例:
DateTime TagName Value
-------- ------- -----
2016-06-02 16:24:51 meter_1_name 66.232818603515625
2016-06-02 16:24:51 meter_2_name 42.3612060546875
2016-06-02 16:24:51 meter_3_name 25.111988067626953
2016-06-02 16:24:51 meter_4_name 4.296875
2016-06-02 16:24:51 meter_5_name NULL
2016-06-02 16:24:51 meter_6_name 3.5083911418914795
2016-06-02 16:24:51 meter_7_name 46.137149810791016
2016-06-02 16:24:51 meter_8_name 71.419265747070312
2016-06-02 16:24:51 meter_9_name 68.337669372558594
2016-06-02 16:24:51 meter_10_name 3.1090855598449707
2016-06-02 16:24:51 meter_11_name 3.0222799777984619
2016-06-02 16:24:51 meter_12_name 2.3900461196899414
2016-06-02 16:24:51 meter_13_name 44.856769561767578
2016-06-02 16:24:51 meter_14_name 64.431419372558594
2016-06-02 16:24:51 meter_15_name 34.657115936279297
2016-06-02 16:24:52 meter_1_name 66.232818603515625
2016-06-02 16:24:52 meter_2_name 42.3612060546875
2016-06-02 16:24:52 meter_3_name 25.111988067626953
2016-06-02 16:24:52 meter_4_name 4.296875
2016-06-02 16:24:52 meter_5_name NULL
2016-06-02 16:24:52 meter_6_name 3.5083911418914795
2016-06-02 16:24:52 meter_7_name 46.137149810791016
2016-06-02 16:24:52 meter_8_name 71.419265747070312
2016-06-02 16:24:52 meter_9_name 68.337669372558594
2016-06-02 16:24:52 meter_10_name 3.1090855598449707
2016-06-02 16:24:52 meter_11_name 3.0222799777984619
2016-06-02 16:24:52 meter_12_name 2.3900461196899414
2016-06-02 16:24:52 meter_13_name 44.856769561767578
2016-06-02 16:24:52 meter_14_name 64.431419372558594
2016-06-02 16:24:52 meter_15_name 34.657115936279297
2016-06-02 16:24:53 meter_1_name 66.232818603515625
2016-06-02 16:24:53 meter_2_name 42.3612060546875
2016-06-02 16:24:53 meter_3_name 25.111988067626953
2016-06-02 16:24:53 meter_4_name 4.296875
2016-06-02 16:24:53 meter_5_name NULL
2016-06-02 16:24:53 meter_6_name 3.5083911418914795
2016-06-02 16:24:53 meter_7_name 46.137149810791016
2016-06-02 16:24:53 meter_8_name 71.419265747070312
2016-06-02 16:24:53 meter_9_name 68.337669372558594
2016-06-02 16:24:53 meter_10_name 3.1090855598449707
2016-06-02 16:24:53 meter_11_name 3.0222799777984619
2016-06-02 16:24:53 meter_12_name 2.3900461196899414
2016-06-02 16:24:53 meter_13_name 44.856769561767578
2016-06-02 16:24:53 meter_14_name 64.431419372558594
2016-06-02 16:24:53 meter_15_name 34.657115936279297
我正在考虑把它变成这样:
DateTime meter_1_value meter_2_value meter_3_value meter_4_value
-------- ------------- ------------- ------------- -------------
2016-06-02 16:24:51 66.2328186035 42.36146875 21.111986762693 5.29687
2016-06-02 16:24:52 70.2328186035 43.36146875 22.111988062695 2.29685
2016-06-02 16:24:53 80.2328186035 40.36120465 23.111988762653 8.29675
2016-06-02 16:24:54 90.2328186035 49.36120685 24.111986762693 5.29875
如您所见,这样会减少很多行,并且可以更轻松地完成求和/平均值。在这种情况下,确定哪个值属于哪个仪表将不是问题。
编辑:行->列查询是hacky,看起来像这样:
DROP VIEW IF EXISTS v_temp;
CREATE OR REPLACE VIEW v_temp AS
(
SELECT m.datatime,
MAX(IF(metername = 1, metervaluevalue, null)) as "meter1",
MAX(IF(metername = 2, metervaluevalue, null)) as "meter2",
MAX(IF(metername = 3, metervaluevalue, null)) as "meter3"
FROM meters m
WHERE m.datatime >= CAST("2016-05-09 00:00:00" AS DATETIME)
AND m.datatime <= CAST("2016-05-11 23:59:00" AS DATETIME)
GROUP BY datatime
);
SELECT datatime,
ROUND(AVG(meter1), 0) as meter1_avg,
ROUND(AVG(meter2), 0) as meter2_avg,
ROUND(AVG(meter3), 0) as meter3_avg
FROM v_temp
GROUP BY DATE(datatime), HOUR(datatime), MINUTE(datatime)
ORDER BY datatime ASC
【问题讨论】:
-
我可能会保留当前的设计。
-
在我看来,存储为更多行(即以规范化形式)的更多优势取决于设计。 stackoverflow.com/questions/9774715/…
-
2700 万行每年听起来并不是不合理的数据量。这要运行多少年?除以 50 是对增长的微小线性变化,与系统中增加的复杂性相比,它几乎没有什么区别。我会更关注性能调优,而不是单数量级的数据缩减。
-
@David 再说一遍,2700 万而不是 2700 万 / 50 = 540k / 年?那我可以运行 27 年没有问题吗?我认为添加新仪表不是问题。我可以编写一些工具来向表中添加新列或其他东西。真正成为问题的是求和和平均。如果我把每一米都排成一排,这很难做到。我不能按米分组,因为我必须按日期时间分组才能获得例如每小时平均值。
-
关系数据库的重点是以normalized形式存储数据。通过将行转为列,您正在对布局进行非规范化。