正确的复合索引索引顺序

ran*_*rat 3 mysql mariadb index-tuning

我有 MySQL (MariaDB) 数据库。我有一个表“传感器”,它从物联网设备收集数据。

每个设备可以记录 4-6 个参数,如温度、湿度、空气质量等。每个设备每分钟发送一次测量值。

有 10-15 个这样的设备。每个设备都有它的deviceid

六栏:

`autoid`(INT,AUTOICREMENT)
`deviceid`(varchar)
`pname`(varchar)         /* name of parameter like temperature,humidty */
`pcode`(INT)             /* code for each parameter like for temperature its 11,humidty its 12 etc */
`datavalue`(double)      /* value of parameter */
`rectime`(INT)           /* UNIX timestamp */
Run Code Online (Sandbox Code Playgroud)

以下是表数据示例:

自体 设备编号 名字 密码 数据值 重新计时
1 sdbjs4b 温度 11 30.54 1621702300
2 sdbjs4b 12 104 1621702300
3 sdbjs4b 气体 13 768 1621702300
4 vsf5bjs 温度 11 31.45 1621702300
5 vsf5bjs 伏特 15 5.10 1621702300

传感器表中几乎有4-5 百万行。

我的查询要求:我必须为每个设备和参数每天获取一些任意时间值的数据。

这是使用的查询:

SELECT * from sensors where deviceid =? AND  pcode = ? AND rectime =?
Run Code Online (Sandbox Code Playgroud)

这保证只会给我一个结果。问题是我需要在嵌套循环中运行这个查询,最坏的情况是 500 次。为什么我需要循环?我需要为每个设备、参数以及两个日期之间的一组给定时间段创建两个日期之间的报告。我必须循环获取时隙的值。

我有一个综合指数(deviceid,rectime,pcode)

如果我将此索引更改为 ,有什么区别(rectime,deviceid,pcode)

一般来说,如果我的查询使用 where 子句中的所有索引列,列顺序在复合索引中是否重要?

Vla*_*sak 5

我认为您使用嵌套循环的方法是次优的。

为什么你不能做这样的事情:

select * from sensors where deviceid =? AND  pcode = ? AND rectime between ? and ?
Run Code Online (Sandbox Code Playgroud)

这将返回整个数据集,您可以在本地处理它。在一个正确的选择中选择 500 或更多行比 500 个单行选择要好。

在这种情况下,我会将聚集索引更改为

(deviceid,pcode,rectime)
Run Code Online (Sandbox Code Playgroud)

您仍然可以保留 autoId 主键,只需将其设为非集群即可。

此外,根据您选择的工作方式,它必须在之后进行键查找才能获得一个额外的行。MySQL AFAIK 不支持包含索引,但即使如此,它也将是表的事实上重新排序的副本,因此聚集索引是有意义的。

至于顺序是否重要……嗯,是的,也不是。鉴于您的数据类型和表的大小,差异将是最小的。