我并不像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天的数据中,但是任何加速它的东西都会受到赞赏。
答案 0 :(得分:3)
您最强的过滤器似乎是GPS_TABLE
过去2天的过滤器。它应该将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
答案 1 :(得分:1)
优化SQL查询通常通过以下方式完成:
首先,添加ACTIVITY_DATE
的索引,以及条件中使用的其他一些字段。