【发布时间】:2015-01-12 14:21:29
【问题描述】:
我在 MySQL 中有以下选择,它产生了正确的结果,但执行起来花费了不必要的时间:
SELECT tblGPSDevices.Email, tblLoc.Lat, tblLoc.Lon, tblLoc.Radius, tblLoc.CreationTimeStamp, tblTrackedUsers.ID, tblTrackedUsers.TrackerDeviceID, tblTrackedUsers.TrackedDeviceID
FROM tblTrackedUsers
INNER JOIN tblGPSDevices ON tblTrackedUsers.TrackedDeviceID = tblGPSDevices.ID
LEFT OUTER JOIN (
SELECT A.DeviceID, A.Lat, A.Lon, A.Radius, A.CreationTimeStamp, A.ID
FROM tblLocations A
INNER JOIN (
SELECT DeviceID, MAX(CreationTimeStamp) AS CreationTimeStamp, MAX(ID) AS ID
FROM tblLocations
GROUP BY DeviceID
) AS B ON A.DeviceID = B.DeviceID
AND A.CreationTimeStamp = B.CreationTimeStamp
AND A.ID = B.ID
) AS tblLoc ON tblLoc.DeviceID = tblGPSDevices.ID
WHERE tblGPSDevices.Validated = 0x01
AND tblGPSDevices.Enabled = 0x01
AND tblTrackedUsers.Validated = 0x01
AND tblTrackedUsers.TrackerDeviceID = 1
ORDER BY tblTrackedUsers.ID;
此查询的运行速度比应有的要慢得多,因为它对 tblLocations 进行全表扫描。
这是真正减慢查询速度的部分:
SELECT A.DeviceID, A.Lat, A.Lon, A.Radius, A.CreationTimeStamp, A.ID
FROM tblLocations A
INNER JOIN (
SELECT DeviceID, MAX(CreationTimeStamp) AS CreationTimeStamp, MAX(ID) AS ID
FROM tblLocations
GROUP BY DeviceID
) AS B ON A.DeviceID = B.DeviceID
AND A.CreationTimeStamp = B.CreationTimeStamp
AND A.ID = B.ID
这里是解释计划:
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY tblTrackedUsers ref TrackerDeviceID,TrackedDeviceID TrackerDeviceID 9 const 14 Using where; Using temporary; Using filesort
1 PRIMARY tblGPSDevices eq_ref PRIMARY PRIMARY 8 tblTrackedUsers.TrackedDeviceID 1 Using where
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2073
2 DERIVED <derived3> ALL NULL NULL NULL NULL 2073
2 DERIVED A eq_ref PRIMARY,DeviceID,CreationTimeStampIndex PRIMARY 8 B.ID 1 Using where
3 DERIVED tblLocations index NULL DeviceID 8 NULL 174058
它对 tblLocations 进行全表扫描,尽管我只需要该表中的一小部分 DeviceID。
我只需要查看从这部分返回的 DeviceID:
INNER JOIN tblGPSDevices ON tblTrackedUsers.TrackedDeviceID = tblGPSDevices.ID
WHERE tblTrackedUsers.TrackerDeviceID = 1
但不幸的是,tblTrackedUsers.TrackedDeviceID 在内部选择中不可见。所以如果我添加
WHERE DeviceID = tblTrackedUsers.TrackedDeviceID
正上方
GROUP BY DeviceID
它不起作用。
我该如何优化这个查询?
仅涉及相关字段的表结构:
tblGPSDevices:
ID |电子邮件 |已验证 |已启用
tblLocations:
ID |设备ID |纬度 |朗 |半径 |创建时间戳
tblTrackedUsers:
ID |跟踪设备ID |跟踪设备ID |已验证
tblLocations.DeviceID、tblTrackedUsers.TrackerDeviceID 和 tblTrackedUsers.TrackedDeviceID 是指向 tblGPSDevices.ID 的外键
此查询的作用:
查询应返回用户正在跟踪的 tblGPSDevices 中的所有设备以及 tblLocations 中的最后位置。确定用户正在跟踪哪些设备的方式由 tblTrackedUsers 确定:select TrackedDeviceID from tblTrackedUsers where TrackerDeviceID = some_value
【问题讨论】:
-
你能给出你正在查询的表的架构吗?并说明查询需要做什么
-
@czifro 我已经用所需信息更新了问题
-
最好发布 CREATE TABLE 和 INSERT 命令或创建 SQL Fiddle。 sqlfiddle.com
标签: mysql sql select left-join inner-join