提高SQL查询性能MAX日期

问题描述

我正在搜索如何基于col1和col2获取最新的事件。

假设我们有下表(所有需要的行都标有*):

col1                   col2                    col3  
---------------------------------------------------------
002478                 ABC                 2019-08-23    *
002478                 ABC                 2019-05-14    
002588                 CVMG                2019-01-07    *
002588                 IP                  2019-01-31    *
002588                 MMG                 2019-09-04    *
002588                 MMG                 2019-08-28    
002588                 NUSA                2019-11-04    *
002588                 NUSA                2019-04-24    
002746                 IE                  2019-01-15    *
003467                 IE                  2020-01-10    
003467                 IE                  2020-03-13    *

通过以下选择,我能够获得基于col1和col2的最新事件。

SELECT t.col1,t.col2,t.col3
FROM 
       teste t
WHERE t.col3 IN (SELECT max(a.col3) 
                 FROM teste a 
                 WHERE a.col1 = t.col1 AND a.col2 = t.col2)

在此示例中,只需大约10 ~ 7 ms即可完成,但是在我的真实数据库中,大约需要1 hour

删除了所有可能的JOINS,并且我到达的最短时间约为55 minutes

使用Progress时,没有window function这样的partition by(我知道)。


还有另一种方法可以解决此问题?我唯一想到的查询就是关于“样式”的。

这是该示例数据库SQL Fiddle

解决方法

编写同一查询的另一种方法是选择不存在较新的相关行的行:

SELECT t.col1,t.col2,t.col3
FROM teste t
WHERE NOT EXISTS
(
  SELECT NULL
  FROM teste t_newer
  WHERE t_newer.col1 = t.col1
    AND t_newer.col2 = t.col2
    AND t_newer.col3 > t.col3
);

这可能更快或更慢或同样快。这取决于您的DBMS在内部如何运行。

使用这两个查询中的任何一个,DBMS都面临着快速查找具有相同col1和col2的其他行的任务。仅使用该表,DBMS将不得不一次又一次地依次读取它。这就是索引起作用的地方。您可以为DBMS提供索引,在其中可以查找表中匹配行的位置。

在您的情况下,您需要一个索引col1和col2,以便提供一种查找相关行的方法。您还可以添加col3,因为这也必须进行比较。也许以col1或col2开始索引并不重要,也许确实如此。表中有多少个不同的col1,有多少个不同的col2?如果一个只有5个不同的值,而另一个只有5,000个,则从一个有5,000个值的索引开始,因为对于一个值,您会发现较少的行,即更快地找到了感兴趣的行。

索引可能看起来像

create index idx on teste (col1,col2,col3);

查询保持不变。 DBMS将查看您的查询并决定是否使用索引。对于给定的查询,我确定它将使用提到的索引,因为查询都是为了快速查找相关行。