如何在低规格系统上的大表上提高 MySQL 性能?

Posted

技术标签:

【中文标题】如何在低规格系统上的大表上提高 MySQL 性能?【英文标题】:How can I improve MySQL performance on a lrge table on low spec system? 【发布时间】:2015-03-19 08:06:50 【问题描述】:

我有一个 Raspberry Pi,我一直在使用它来记录从一堆 1-Wire 传感器收集的家庭温度数据。多年来,这些数据已全部收集到 mysql 数据库中。我使用 Raspbian 发行版和默认的 MySQL 配置。我现在有一个包含超过一百万条记录的表,并且我的 Pi 运行查询非常缓慢。

这里是 TemperatureRecords 表的描述:

+--------------+----------+------+-----+---------------------+-------+
| Field        | Type     | Null | Key | Default             | Extra |
+--------------+----------+------+-----+---------------------+-------+
| timeRecorded | datetime | NO   | PRI | 0000-00-00 00:00:00 |       |
| sensorName   | char(3)  | NO   | PRI |                     |       |
| tempValue    | float    | YES  |     | NULL                |       |
+--------------+----------+------+-----+---------------------+-------+

我记录日期和时间、3 个字符的传感器名称和温度值。 我想运行两个查询,一个选择某个传感器的当前(最近)温度,一个选择当天的最高温度。

当前温度示例:

SELECT ROUND(tempValue, 1) as tempValue 
FROM TemperatureRecords 
WHERE DATE(timeRecorded) = '2015-01-20' AND HOUR(timeRecorded) = '20' AND sensorName = 'abc' 
ORDER BY timeRecorded DESC LIMIT 1;

最高温度示例:

SELECT MAX(tempValue) 
FROM TemperatureRecords 
WHERE DATE(timeRecorded) = '2015-01-20' AND sensorName = 'abc';

不幸的是,这些可能需要 10-20 秒才能完成,这太慢了,尤其是当我想从多个传感器检索数据以同时显示在网页上时。

我已经尝试向表中添加额外的索引,但这并没有带来任何改进,而且我不确定我是否完全理解索引。我还尝试将 MySQL 配置用于 /usr/share/doc/mysql-server-5.5/examples/my-small.cnf 中的小型系统,有人告诉我这可能会提高性能,但无济于事。

我对 MySQL 的了解有些基础。现在我的数据已经变得如此庞大,我是否对 Raspberry Pi 抱有太大期望,或者我可以做些什么来改进我的设置?

【问题讨论】:

是的。尝试使用 RANGE 查询 【参考方案1】:

罪魁祸首是WHERE DATE(timeRecorded) = '2015-01-20' - 它为所有行(无论它们是否匹配)计算DATE(),并禁止使用索引。

试试:WHERE timeRecorded >= '2015-01-20 00:00:00' and timeRecorded < '2015-01-21 00:00:00'

详情请见this SO question!

【讨论】:

【参考方案2】:

调用DATE() 之类的方法会立即给您带来麻烦。这些不能被索引,没有索引你死在水里。

如果您经常调用这些,请创建一个 DATE 列,其中包含您正在搜索的数据。您可能还需要一个列来捕获要提取的小时信息。

数据库规范化原则一直适用,直到您遇到这样的情况,即理想形式的速度慢得令人无法接受。在这种情况下,您需要仔细去规范化以解决这些问题。保持这样的数据同步可能很棘手,因此请确保在更改主日期时使所有这些派生列保持最新。

如果您可以将DATETIME 缩小到某个时间范围,您可能有机会按原样使用它,例如:

WHERE timeRecorded BETWEEN '2015-01-20 20:00:00' AND '2015-01-20 20:59:99'

如果可行,您现有的索引将适用。

【讨论】:

【参考方案3】:

我认为您所追求的可以在 Raspberry Pi 上实现,您只需要更改处理繁重查询的方式即可。

如果是历史数据,则每天处理数据并将其保存到另一个(更小、更快)的表格中,以便网页快速引用。

每小时平均值也仅每小时运行一次,保存到单独的表格中。

将当前温度和记录放在缓冲表中,但只有网页可以访问缓冲表。

它可能不那么准确,但希望差异会很小,但您应该会看到速度大幅提升

【讨论】:

以上是关于如何在低规格系统上的大表上提高 MySQL 性能?的主要内容,如果未能解决你的问题,请参考以下文章

mysql 表很少,一个大表上的子查询执行缓慢

大表上的慢 MySQL SELECT

MySQL分区和分表

如何在大表上优化这个 mysql 连接?

Mysql + 大表 = 慢查询?

进阶Mysql分库分表方案,如何分,怎样分?