3

我有以下数据库架构: 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 查询是否有更好的方法。

4

4 回答 4

1

我建议您尝试在列上放置索引:

D.Id
MH.Id_Device 
MH.Id_Meter
M.Id 
MR.Id_Meter 
MR.Date
于 2012-10-04T14:48:02.827 回答
1

如果那是您正在运行的查询,它看起来不是最理想的。你真的不需要 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";
于 2012-10-04T15:12:32.993 回答
0

我的猜测是,由于缺少索引,它正在执行表扫描。尝试注释掉这一点,看看它是否有所改善:

AND MR.Date>="2012-10-04" 
AND MR.Date<="2012-10-04"

如果是这样,请尝试在 MR.Date 上建立索引。

于 2012-10-04T14:48:07.683 回答
0

索引肯定会有所帮助。适当地运行 EXPLAIN 和索引。索引所有外键和日期字段。这是有关 JOIN 索引的更多详细信息。

http://hackmysql.com/case4

通常最简单的解决方案是避免过于复杂的查询。您要加入 4 张桌子。您真的需要所有 4 个表中的所有数据吗?我通常避免 SELECT * 查询来强迫自己确保我只获取我需要的数据。

于 2012-10-04T15:04:24.283 回答