0

我对 SQL 中的快捷方式不太了解,所以我希望利用这里的智慧来帮助加快我正在使用的查询。我目前正在使用 Oracle 8i。

我有一个查询:

SELECT 
    NAME_CODE, ACTIVITY_CODE, GPS_CODE 
FROM
    (SELECT 
         a.NAME_CODE, b.ACTIVITY_CODE, a.GPS_CODE, 
         ROW_NUMBER() OVER (PARTITION BY a.GPS_DATE ORDER BY b.ACTIVITY_DATE DESC) AS RN
     FROM GPS_TABLE a, ACTIVITY_TABLE b
     WHERE a.NAME_CODE = b.NAME_CODE
       AND a.GPS_DATE >= b.ACTIVITY_DATE 
       AND TRUNC(a.GPS_DATE) > TRUNC(SYSDATE) - 2)
WHERE 
    RN = 1

这大约需要 7 分钟或 10 秒来运行。

现在GPS_TABLE是 6.586.429 行,并且随着新的 GPS 坐标被输入系统而继续增长,每天它在 6 列中增长约 8.000 行。

当前ACTIVITY_TABLE为 1.989.093 行,并且随着新活动进入系统而继续增长,每天它在 31 列中增长约 2.000 行。

所以总而言之,这些都不是小表,我知道运行这个或类似的查询总会有时间。如您所见,我已经将其限制为仅过去 2 天的数据,但任何可以加快速度的东西都将不胜感激。

4

2 回答 2

3

您最强的过滤器似乎是最近 2 天的过滤器GPS_TABLE。它应该过滤GPS_TABLE到大约 15k 行。因此,改进的最佳候选之一是列上的索引GPS_DATE

您会发现您的过滤器TRUNC(a.GPS_DATE) > TRUNC(SYSDATE) - 2等同于a.GPS_DATE > TRUNC(SYSDATE) - 2,因此如果您更改查询,您的列上的简单索引将起作用。如果你不能改变它,你可以在TRUNC(GPS_DATE).

一旦有了这个索引,我们就需要访问ACTIVITY_TABLE. 您加入的问题是我们将获得所有旧活动,因此我们将获得表格的很大一部分。这意味着连接在索引扫描中效率不高。

我建议您定义一个索引ACTIVITY_TABLE(name_code, activity_date DESC)和一个 PL/SQL 函数,该函数将专门使用此索引以最少的工作量检索最后一个活动:

CREATE OR REPLACE FUNCTION get_last_activity (p_name_code VARCHAR2, 
                                              p_gps_date DATE) 
RETURN ACTIVITY_TABLE.activity_code%type IS
   l_result ACTIVITY_TABLE.activity_code%type;
BEGIN
   SELECT activity_code
     INTO l_result
     FROM (SELECT activity_code
             FROM activity_table
            WHERE name_code = p_name_code
              AND activity_date <= p_gps_date
            ORDER BY activity_date DESC)
     WHERE ROWNUM = 1;
   RETURN l_result;
END;

修改您的查询以使用此功能:

SELECT a.NAME_CODE,
       a.GPS_CODE,
       get_last_activity(a.name_code, a.gps_date)
  FROM GPS_TABLE a
 WHERE trunc(a.GPS_DATE) > trunc(sysdate) - 2
于 2012-09-04T11:37:36.380 回答
1

优化 SQL 查询通常通过以下方式完成:

  1. 添加一些索引
  2. 尝试不同的方式来获取相同的信息

因此,首先为 添加一个索引ACTIVITY_DATE,也许还有一些在条件中使用的其他字段。

于 2012-09-04T11:36:57.190 回答