每30分钟从动物收容所中的几个动物笼收集每小时温度读数,并将它们倒入文件中。 cron处理该数据并将其插入MYSQL数据库。目前,当天所有48个温度读数都存储在一个表格中,我随着数据的进入更新它们,或者如果没有记录,则会创建一个存储第一个温度的新记录。
我们目前有一个Cage信息表和一个笼温读数表。 我们的笼子总数是45。 我们拥有的数据量是7年(大约2557天)。 温度表的记录总数为:115,065
我们将在系统中添加不同的位置和额外的笼子,因此笼子的总数将大于1,000。我们希望数据使用量能够快速增长。
是否有更有效的方法来构建下表以优化读取速度?这些数据用于生成每天早上显示的每个笼子的图表,以及30分钟的尸检,以检查笼子内的通风不足。
当前温度表如下:
CREATE TABLE `temperature_readings` (
`CAGE_ID` int(10) NOT NULL DEFAULT '0',
`INT_VALUE_0000` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0030` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0100` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0130` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0200` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0230` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0300` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0330` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0400` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0430` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0500` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0530` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0600` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0630` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0700` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0730` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0800` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0830` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0900` decimal(5,2) DEFAULT NULL,
`INT_VALUE_0930` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1000` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1030` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1100` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1130` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1200` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1230` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1300` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1330` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1400` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1430` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1500` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1530` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1600` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1630` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1700` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1730` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1800` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1830` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1900` decimal(5,2) DEFAULT NULL,
`INT_VALUE_1930` decimal(5,2) DEFAULT NULL,
`INT_VALUE_2000` decimal(5,2) DEFAULT NULL,
`INT_VALUE_2030` decimal(5,2) DEFAULT NULL,
`INT_VALUE_2100` decimal(5,2) DEFAULT NULL,
`INT_VALUE_2130` decimal(5,2) DEFAULT NULL,
`INT_VALUE_2200` decimal(5,2) DEFAULT NULL,
`INT_VALUE_2230` decimal(5,2) DEFAULT NULL,
`INT_VALUE_2300` decimal(5,2) DEFAULT NULL,
`INT_VALUE_2330` decimal(5,2) DEFAULT NULL,
PRIMARY KEY (`CAGE_ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
我的想法是将多个温度读数标准化为halfhour_read表,例如
halfhour_read{
- cage_id
- datetime
- temperature reading
}
或通过cage_id或今天(日期)对Hash temperature_readings进行哈希,以便对其进行分区。
据我所知,第一个选项会将记录数量从115,065增加到5,523,120,相比之下会快速增长,从而产生未来的空间问题。
答案 0 :(得分:4)
是的,规范化您的结构。只是为了好玩,尝试使用您当前的结构编写以下查询:笼子A上周的温度峰值是多少?
按照你的直觉使用这个结构:
CREATE TABLE readings (
cage_id INT,
dateofreading DATETIME,
temperature DECIMAL(10,2),
PRIMARY KEY (cage_id, dateofreading),
INDEX (dateofreading, cage_id) -- suggested index, useful for time-based queries
)
预期行大小(仅限数据):4 + 8 + 4 = 16字节。
16字节x每天48个读数x 10,000个笼子x 365天=每年2.6 GB。如果需要,可以乘以3或4来提供索引。无论如何,不要担心存储空间。
由于正确的索引,即使它包含数十亿条记录,也可以从这个表中提取数据。无论如何,你的工作集(过去几周的数据)可能总是适合你的记忆。
(如果您的要求是“100,000个笼子,每天读数为4,800,000”,那么您的主要关注点不是存储空间,而是每秒处理数百万次插入)
要将工作数据集保持在合理的大小,是的,对表进行分区,或者只是不时地将旧记录移动到存档表中。
答案 1 :(得分:1)
绝对正常化......但你需要一个更大的磁盘:-)
实际上,500万短行并不是真正的大量数据。 MySQL可以处理更多。 500万reading
行大约为100MB。
您还应该考虑按年份对数据进行分区,因为历史数据永远不会发生变化。