我远离MYSQL专家,而且我正在努力解决相对复杂的问题。
我有两张桌子:
包含以下列的数据表:
`Location` bigint(20) unsigned NOT NULL,
`Source` bigint(20) unsigned NOT NULL,
`Param` bigint(20) unsigned NOT NULL,
`Type` bigint(20) unsigned NOT NULL,
`InitTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`ValidTime` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`Value` double DEFAULT NULL
包含以下列的列表的位置组表:
`Group` bigint(20) unsigned NOT NULL,
`Location` bigint(20) unsigned NOT NULL,
数据表存储感兴趣的数据,其中每个值都是'适用于特定的有效时间'。但是,表中的数据来自定期运行的计算。运行计算的初始化时间存储在“初始化时间”中。领域。具有特定初始化时间的给定计算可能导致10个值以有效时间(A-J)输出。使用更新的初始化时间的更新近的计算可能导致以有效时间(B-K)输出另外10个值。因此,可用值存在重叠。我总是想要最新inittime的值和ValidTimes的结果集(即max(inittime))。
我可以使用以下查询确定最新的inittime:
SELECT MAX(InitTime)
FROM Data
WHERE
Location = 100060 AND
Source = 10 AND
Param = 1 AND
Type = 1;
这需要0.072秒才能执行。
但是,使用它作为子查询从Data表中检索数据会导致执行时间为45秒(这是一个非常大的表,但不是非常荒谬的)。
子查询:
SELECT Location, ValidTime, Value
FROM Data data
WHERE Source = 10
AND Location IN (SELECT Location FROM Location Group WHERE Group = 3)
AND InitTime = (SELECT max(data2.InitTime) FROM Data data2 WHERE data.Location = data2.Location AND data.Source = data2.Source AND data.Param = data2.Param AND data.Type = data2.Type)
ORDER BY Location, ValidTime ASC;
(为简洁起见,Snipped ValidTime限定符)
我知道可能有一些优化会对此有所帮助,但我不知道从哪里开始。相反,我创建了一个存储过程来有效地执行MAX(InitTime)查询,但由于MAX(InitTime)由Location,Source,Param和Type的组合决定,我需要传入组成特定的所有位置组。在实现必须有一种更简单的方法之前,我为此实现了基于游标的存储过程。
不考虑通过索引进行优化的问题,如何使用针对给定位置组,源,参数和类型的最新InitTime有效地对数据表执行查询?
提前致谢!
答案 0 :(得分:0)
MySQL可以通过子查询(有时)优化IN
。此外,索引可能会有所帮助。所以,我会把查询写成:
SELECT d.Location, d.ValidTime, d.Value
FROM Data d
WHERE d.Source = 10 AND
EXISTS (SELECT 1 FROM LocationGroup lg WHERE d.Location = lg.Location and lg.Group = 3) AND
d.InitTime = (SELECT max(d2.InitTime)
FROM Data d2
WHERE d.Location = d2.Location AND
d.Source = d2.Source AND
d.Param = d2.Param AND
d.Type = d2.Type
)
ORDER BY d.Location, d.ValidTime ASC;
对于此查询,您需要data(Location, Source, Param, Type, InitTime)
和LocationGroup(Location, Group)
以及data(Source, Location, ValidTime)
上的索引。