我有以下数据库架构: https://dl.dropbox.com/u/37915176/schema.PNG
我在 meter_relevation 中有超过 200 万条记录。数据来自多个电表,这些电表与具有 meter_history 表的电器(设备)相关联。
我尝试获取特定日期范围内的设备数据:
SELECT MR.*
FROM device AS D, meter_history AS MH, meter AS M, meter_relevation AS MR
WHERE D.Id=MH.Id_Device
AND MH.Id_Meter=M.Id
AND M.Id=MR.Id_Meter
AND D.Id="8"
AND MR.Date>="2012-10-04"
AND MR.Date<="2012-10-04"
但是性能很慢,即使在指定的日期范围内没有记录,我也可以获得 10 秒。
我尝试了 EXPLAIN,我清楚地看到我的查询不是最优的,在 meter_relevation 表上列出了总行数,超过 200 万:https://dl.dropbox.com/u/37915176/explain.png
有什么建议吗?有一个更好的方法?当然我可以在客户端做一些工作并分成几个查询。但我想知道对于单个 SELECT 查询是否有更好的方法。
最佳答案
如果那是您正在运行的查询,它看起来不是最优的。你真的不需要 D 表,对吗?查看如何通过 MH.Id_device = "8"
满足设备上的条件。
但是假设还有其他字段没有显示,那么让我们重写:
SELECT MR.*
FROM meter_relevation AS MR
JOIN meter AS M ON ( M.Id = MR.ID_Meter )
JOIN meter_history AS MH ON ( MH.Id_Meter = M.Id )
JOIN device AS D ON ( D.Id=MH.Id_Device AND D.Id = "8" )
WHERE
MR.Date BETWEEN "2012-10-04" AND "2012-10-04";
所以我们需要索引。第一个最重要
CREATE INDEX mr_ndx ON meter_relevation ( Date, Id_Meter );
但也尝试删除上面的索引并改用:
CREATE INDEX mr_ndx ON meter_relevation ( Id_Meter, Date );
CREATE INDEX m_ndx ON meter(Id); -- This probably already exists
CREATE INDEX mh_ndx ON meter_history( Id_Device, Id_Meter );
CREATE INDEX d_ndx ON device (Id); -- This too probably already exists
如果这样写,上面的代码等同于(但 MySQL 应该意识到这一点,所以我认为它不会减慢你太多)
SELECT MR.*
FROM meter_relevation AS MR
JOIN meter AS M ON ( MR.ID_Meter = M.Id)
JOIN meter_history AS MH ON (MH.Id_Device = "8" AND MH.Id_Meter = M.Id)
WHERE
MR.Date BETWEEN "2012-10-04" AND "2012-10-04";
关于mysql - 缓慢的 MySQL SELECT 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12729907/