我有以下名为‘LOG_DATA’的MySQL表-MyISAM

没有 keys ,没有索引,什么都没有.

VarId INT(11)
VarValue float
CurDate datetime(3)

此表的目的是记录数据,VarID是一个整数,指向提供此实际变量的‘名称’的另一个表.因此,特定的LOG_DATA表包含所有的过程数据,由VarID分隔,并且通常在特定的日期范围(CurDate)内.由于每个变量的日志(log)记录间隔约为100ms,因此该表的增长速度相当快.当前数据集有2亿条记录.

示例查询:

SELECT
  CurDate AS "time",
  VarValue AS 'Motor Power'
FROM log_data
WHERE
  CurDate BETWEEN FROM_UNIXTIME(1699511240) AND FROM_UNIXTIME(1699543207) AND VarId = 6

我在找出加速这些类型的查询的最佳方式时遇到了问题.当我在Grafana中显示这些变量时,一个面板可以有10个这样的查询(具有不同的VarID).然后,单个面板需要大约20秒才能加载.

优化这些类型的查询的最佳方式是什么?

我试着使用主键‘id’,在CurDate字段上建立索引,但这没有帮助.它甚至将查询时间增加到1分钟以上.此外,从InnoDB切换到MyISAM也带来了性能上的优势,但我仍然希望它能更快.

推荐答案

在两列上添加索引:

ALTER TABLE log_data ADD INDEX (VarId, CurDate);

列的顺序很重要,它由查询中的条件决定.请看我对Does Order of Fields of Multi-Column Index in MySQL Matter?的回答

您还可以从将VarValue列添加到索引中获得好处,将其设置为covering index.,这样查询就可以只通过读取索引来获得结果,因此它根本不需要触及表行.

使用这个索引,而不是我上面显示的那个.

ALTER TABLE log_data ADD INDEX (VarId, CurDate, VarValue);

使用EXPLAIN确认查询正在使用索引.例如,如果您要搜索的特定值出现在很大一部分行上,优化器可能会决定不值得使用索引.

我不推荐使用MyISAM.当然,性能很好,但更重要的是支持对表的并发更新,并且不丢失数据.请看我对MyISAM versus InnoDB的回答.

Mysql相关问答推荐

过程/别名是有点长的MySQL命令的一部分吗?

MySQL InnoDB:可以在没有回滚损失的情况下从运行的查询中进行大型插入吗

客户跨订阅的跨时间线计数

WordPress的sql命令从帖子中删除随机文本

从 R 脚本创建新的 MYSQL 数据库

0000-00-00 00:00:00 表中的日期设置为 NOT NULL

使用适配器设计模式和外观设计模式实现

MYSQL除以零警告,奇怪的行为

总行大小不超过 65535,但我得到行大小太大.所用表类型的最大行大小,不包括 BLOB,是 65535错误

MYSQL如何将虚拟列添加到现有表中

使用 ON DUPLICATE KEY 将列增加一定数量 MySQL NodeJS

DECIMAL(m, n) 在 64 位系统中如何表示?

为什么在有 BEGIN 和 END 时为存储过程指定分隔符?

动态创建内联 SQL 表(用于排除左连接)

MySQL:使用来自查询的信息创建一个新表

如何在 MySQL 中为用户设置默认架构

如何在特定数据库中创建表?

MySQL查询/子句执行顺序

MySQL:唯一字段需要是索引吗?

来自 MySQL 中多个表的 COUNT(*)