Mysql 在子查询中,快速查询速度会减慢
我有一个疑问:Mysql 在子查询中,快速查询速度会减慢,mysql,sql,subquery,Mysql,Sql,Subquery,我有一个疑问: SELECT timestmp FROM devicelog WHERE device_id = 5 ORDER BY id DESC LIMIT 1 这需要不到0.001秒的时间来获取,但一旦我将其放入子查询中,它的速度会降低到大约3.05秒。有什么理由解释它为什么会这样做,或者我如何补救它 下面是我要优化的第二个查询: SELECT device.id, (SELECT timestmp FROM devicelog WH
SELECT timestmp
FROM devicelog
WHERE device_id = 5
ORDER BY id DESC LIMIT 1
这需要不到0.001秒的时间来获取,但一旦我将其放入子查询中,它的速度会降低到大约3.05秒。有什么理由解释它为什么会这样做,或者我如何补救它
下面是我要优化的第二个查询:
SELECT device.id,
(SELECT timestmp
FROM devicelog
WHERE device_id = device.id
ORDER BY id DESC LIMIT 1) as timestmp
FROM device
表设备中只有大约10-15条记录devicelog有几百万条记录,所以我假设它逐个遍历每条记录,然后执行子查询,但显然它在做其他事情。devicelog的PK是id,device中的PK也是它的id。devicelog上有一个timestmp的索引,它是日期时间和设备id,也是返回devicelog的FK。还有其他的索引,但它们是不相关的东西,如名称、描述等
我只需要它在设备中循环,然后显示最后的时间戳记录
如果我在PHP中列出每个设备,然后分别执行第一个查询,它的性能会非常好,但我希望在一个完整的查询中执行。比如,我可以做一些类似伪代码的事情:
foreach($row in <devicelog>)
query('<first query> where id = $row[id]')
在devicelog上执行整个连接的成本太高,因为计数太高。尝试使用内部连接
SELECT d.id, dl.timestamp
FROM device d
INNER JOIN devicelog dl
ON dl.device_id = d.id
ORDER BY d.id DESC LIMIT 1
列出所有设备,您可以考虑通过
SELECT d.id, dl.timestamp
FROM device d
INNER JOIN devicelog dl
ON dl.device_id = d.id
GROUP BY d.id
ORDER BY d.id DESC
编辑:
如果您有许多索引,最好为列id编制索引
试试这个
ALTER TABLE `device` ADD INDEX `id` (`id`)
根据对第一个答案的评论,您的问题和查询与您要查找的内容不匹配 你可以做的是对每个设备进行预聚合,以获得最大ID日志,然后将其加入到设备的主列表中
SELECT
d.name,
d.id,
DeviceMax.lastTime
from
device d
LEFT JOIN ( select dl.device_id,
max( dl.timestamp ) lastTime
from
devicelog dl
group by
dl.device_id ) as DeviceMax
ON d.id = DeviceMax.device_id
现在,如果您需要设备日志中的其他内容来获取特定条目,我们可以添加到该条目中
LEFT JOIN devicelog dl2
on DeviceMax.Device_id = dl2.Device_id
AND DeviceMax.lastTime = dl2.timestamp
然后可以从添加到查询中的dl2别名中获取任何其他列
另外,对于您的设备日志表,我会在设备id上有一个覆盖索引,timestamp
反馈意见
然后我会给你一个建议,这在web开发领域也是很常见的,当有人需要最高数量、大部分内容或最新的内容时
仅从一个方面取消设备表的规格化。。。为LastDeviceLogID添加一列。然后,每当您的DeviceLog添加了一个条目时,您只需使用一个后插入触发器即可
update Device
set LastDeviceLogID = newRecord.DeviceLogID
where ID = newRecord.Device_ID
列可能不精确,但原则是存在的。这样,你就不需要做一个极限1,MAX,等等,并且浏览你的数百万条记录,你可以像做一样简单
SELECT
d.name,
d.id,
dl.timestamp,
dl.othercolumns
from
device d
LEFT JOIN devicelog dl
on d.LastDeviceLogID = dl.DeviceLogID
这对于设备中的一行是可以的,但我需要列出所有设备以及最后一条devicelog记录。由于限制1,仍然只返回1行。不幸的是,大约花费了6.5秒。此查询非常简单。你能展示你的解释表吗?这都是基于对他的问题的误解,而不是根据他对你以上答案的第一次评论,他们想要什么。尝试了一下,大约需要7秒钟。设备id PK和时间戳上有几个索引。@RalphWiggum,非规范化技术的修订答案是的,我认为插入触发器是最好的方法,但试图避免使用插入触发器。