我有一张桌子,上面有设备的GPS数据logs(id - PK AI, device_id - FK, lat - DECIMAL, long - DECIMAL, time - DATETIME)
的日志。 ID是一个主键,并且有一个index on (id, device_id)
,我想获取每个设备的最新记录。
我当前的查询是:
SELECT * FROM devices
WHERE devices.id IN (
SELECT MAX(id) FROM devices GROUP BY device_id
)
在具有150万条记录和5个唯一设备的表上,查询需要8秒钟。有可能对其进行优化吗?这些设备每秒都在发送数据,我预计总共有2000个设备。
即使使用5台设备,速度也太慢了。
我遇到的另一个查询是选择某个时间段内设备的路由。一天中也要花10秒。
MySQL是执行任务的正确选择吗?我应该选择另一个数据库吗?有没有一种方法可以使查询更快?
答案 0 :(得分:2)
我建议以下内容。首先,将代码重写为:
SELECT d.*
FROM devices d
WHERE d.id = (SELECT MAX(d2.id) FROM devices d2 WHERE d2.device_id = d.device_id);
但是首先在devices(device_id, id)
上创建一个索引。
编辑:
我想知道一些外部优化是否有帮助,例如使用datetime
:
SELECT d.*
FROM devices d
WHERE d.datetime >= NOW() - INTERVAL 1 HOUR AND
d.id = (SELECT MAX(d2.id)
FROM devices d2
WHERE d2.device_id = d.device_id AND
d2.datetime >= NOW() - INTERVAL 1 HOUR
);
为此,您还希望在devices(datetime, device_id)
上建立索引。
答案 1 :(得分:1)
尝试这两个查询中的每一个。通常,您的“最大行”查询行中至少有一个对我有效。
查询1:
SELECT
d.*
FROM devices d
LEFT OUTER JOIN devices larger_d
ON larger_d.device_id = d.device_id
AND larger_d.id > d.id
WHERE larger_d.device_id IS NULL
查询2:
SELECT
d.*
FROM devices d
INNER JOIN (
SELECT
MAX(id) AS id,
device_id
FROM devices d
GROUP BY device_id
) largest_d
ON largest_d.device_id = d.device_id
AND largest_d.id = d.id
在两种情况下,运行这些查询之前,您都需要在(device_id,id)
上建立索引。
为回应您对其他人的回答的评论,(id,device_id
)索引与我们建议的索引不同。您无需删除它,但是它会降低插入速度(就像所有索引一样)。但是,对于该查询而言,它没有用,因此,如果没有特定原因保留它,则可以将其删除。