我有一个表,其架构例如
EventTime DATETIME(6),
EventType VARCHAR(20),
Number1 INT,
Number2 INT,
Number3 INT,
...
此表中有大量行,但是对于此查询,我只感兴趣,例如,其中有数千行位于EventTime
的两个给定值之间。 EventTime
上有一个索引,如果我只是做类似的事情
SELECT * FROM table WHERE EventTime >= time1 and EventTime <= time2;
然后便可以立即返回相关行。
在此时间窗口的行中,我想精确地提取其中Number1
对于具有该EventType
的任何行最大的行。换句话说,我想做与此查询等效的事情:
SELECT * FROM
(SELECT EventType, MAX(Number1) as max_Number1
FROM table
WHERE EventTime >= time1 AND EventTime <= time2
GROUP BY EventType) AS a
LEFT JOIN
(SELECT * FROM table
WHERE EventTime >= time1 AND EventTime <= time2) AS b
ON a.EventType = b.EventType AND a.max_Number1 = b.Number1)
这似乎应该可以正常工作-我可以运行每个子查询,即
SELECT EventType, MAX(Number1) as max_Number1
FROM table
WHERE EventTime >= time1 AND EventTime <= time2
GROUP BY EventType;
和
SELECT * FROM table
WHERE EventTime >= time1 AND EventTime <= time2;
几乎是瞬间完成的,因此此时产生想要的结果应该不太困难:数据库可以通过EventType
对两个子查询的结果进行排序或索引,然后进行匹配。
但是,当我实际运行此程序时,它需要永远。我不知道要花多长时间,因为我从未让它完成,但是它花费的时间比我手动提取两个查询的结果并在其他位置进行合并所需的时间长。
问题:
难度:由于此表有数百亿行,因此向其添加任何其他索引将非常昂贵。
答案 0 :(得分:1)
您实际上已经非常接近一个好的查询了。您的主要缺点可能是在时间范围内从table
中选择所有内容的情况下左键联接。请尝试以下操作:
SELECT * FROM
table b
INNER JOIN (
SELECT EventType, MAX(Number1) as max_Number1
FROM table
WHERE EventTime >= time1 AND EventTime <= time2
GROUP BY EventType
) AS a
ON a.EventType = b.EventType
AND a.max_Number1 = b.Number1
WHERE b.EventTime >= time1 AND b.EventTime <= time2
理想情况下,它会附有索引(EventType,EventTime)
。请在您的问题中提供SHOW CREATE TABLE table
,以便我们查看您当前拥有的索引。我们可以调整现有索引,或帮助您删除不需要的索引,以允许添加此新索引。
免责声明:我的经验几乎完全是在MySQL和InnoDB中,但是我认为这对于MariaDB和MyISAM还是有帮助的。