我的情况很难解释,但我会尝试。
我说,我有50米,每一分钟都输出一些值,我现在已经建了一个像这样的桌子,每分钟有50行添加到每个米的表中,如下所示:
每分钟50行:
id, datetime, meternumber, metervalue
然后我有另一张表:
id, meternumber, metername
这样我就可以为每个meternumber加入meternames。基本的东西。
然而,这很快成为一个问题,因为每分钟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
正如您所看到的那样,行数会减少很多,而且总和/平均值可以通过这种方式更轻松地完成。在这种情况下确定哪个值属于哪个仪表不会有问题。
编辑:row->列查询很糟糕,如下所示:
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
答案 0 :(得分:1)
基本上将这50行转换为列是个好主意 桌子?
在您的位置,我会保留现有结构,并添加一个汇总表,用于维护每个仪表的记录数量以及总和。我不打算保持平均值,因为可以很容易地从计数和总和中计算出来。
这基本上将行数除以50并进行求和 更容易,因为现在我可以将每一行加起来得到:
id,datetime,meter_1_value_summed,meter_2_value_summed,..., meter_n_value_summed
基本上将这50行转换为列是个好主意 桌子?我也尝试过做
我相信这不会给你一个明确的优势,因为你将进行全表扫描并计算所有50列。这可能会比目前的总和要慢得多。
使用Gordon建议的索引将帮助您获得单个仪表的总和和平均值,但如果您需要对所有仪表求和并求平均值,您仍将阅读全表。慢。
摘要表。
我建议的汇总表就是这样的
meter_number, num_records, summation.
您将使用触发器更新此表,以便计算是一项微不足道的补充。检索总和和平均值是一个简单的查询,您只需要读取50条记录。除了summation/num_records
之外没有计算。
答案 1 :(得分:0)
这可能是一个棘手的设计问题。目前的设计有一定的优势:
您提出的设计涉及对数据进行非规范化。这也有一些优点:
1500万行不是特别大。而且,每秒少于一行的负载对数据库来说不是很大的负载。您应该能够使用适当的索引和分区来使当前版本正常工作。
特别是,对特定仪表的值求和应该很快。所以查询如:
select sum(value), avg(value)
from t
where meternumber = 1;
(meternumber, datetime, value)
上的索引应该非常快。
答案 2 :(得分:0)
如果将仪表转换为柱状格式对你来说效果更好,并为你提供所需的结果,那么一定要去吧!具有几百列的表对于任何RDBMS都没有问题,只有具有数百万行的表; MySQL可以在任何一个方向上扩展。关键是使用任何方法以最少的维护为您提供最佳结果,柱状方法看起来是一个很好的解决方案。