这是我的查询,
SELECT ID As Col1,
(
SELECT VID FROM TABLE2 t
WHERE (a.ID=t.ID or a.ID=t.ID2)
AND t.STARTDTE =
(
SELECT MAX(tt.STARTDTE)
FROM TABLE2 tt
WHERE (a.ID=tt.ID or a.ID=tt.ID2) AND tt.STARTDTE < SYSDATE
)
) As Col2
FROM TABLE1 a
Table1有48850条记录,Table2有15944098条记录。
我在TABLE2中有关于ID,ID和amp;的单独索引。 STARTDTE,STARTDTE,ID,ID2&amp; STARTDTE。
查询仍然太慢。如何改进?请帮忙。
答案 0 :(得分:3)
我猜测内部查询中的OR
搞乱了优化器使用索引的能力。此外,我不建议使用扫描所有TABLE2
给定其大小的解决方案。
这就是为什么在这种情况下我会建议使用一个能够有效检索您正在寻找的信息的函数(每次调用2个索引扫描):
CREATE OR REPLACE FUNCTION getvid(p_id table1.id%TYPE)
RETURN table2.vid%TYPE IS
l_result table2.vid%TYPE;
BEGIN
SELECT vid
INTO l_result
FROM (SELECT vid, startdte
FROM (SELECT vid, startdte
FROM table2 t
WHERE t.id = p_id
AND t.startdte < SYSDATE
ORDER BY t.startdte DESC)
WHERE rownum = 1
UNION ALL
SELECT vid, startdte
FROM (SELECT vid, startdte
FROM table2 t
WHERE t.id2 = p_id
AND t.startdte < SYSDATE
ORDER BY t.startdte DESC)
WHERE rownum = 1
ORDER BY startdte DESC)
WHERE rownum = 1;
RETURN l_result;
END;
您的SQL将成为:
SELECT ID As Col1,
getvid(a.id) vid
FROM TABLE1 a
确保table2(id, startdte DESC)
和table2(id2, startdte DESC)
都有索引。索引的顺序非常重要。
答案 1 :(得分:1)
可能会尝试以下方法,但未经测试。
WITH max_times AS
(SELECT a.ID, MAX(t.STARTDTE) AS Startdte
FROM TABLE1 a, TABLE2 t
WHERE (a.ID=t.ID OR a.ID=t.ID2)
AND t.STARTDTE < SYSDATE
GROUP BY a.ID)
SELECT b.ID As Col1, tt.VID
FROM TABLE1 b
LEFT OUTER JOIN max_times mt
ON (b.ID = mt.ID)
LEFT OUTER JOIN TABLE2 tt
ON ((mt.ID=tt.ID OR mt.ID=tt.ID2)
AND mt.startdte = tt.startdte)
答案 2 :(得分:1)
您可以查看analytic functions以避免必须两次击中第二张桌子。这样的事情可能有用:
SELECT id AS col1, vid
FROM (
SELECT t1.id, t2.vid, RANK() OVER (PARTITION BY t1.id ORDER BY
CASE WHEN t2.startdte < TRUNC(SYSDATE) THEN t2.startdte ELSE null END
NULLS LAST) AS rn
FROM table1 t1
JOIN table2 t2 ON t2.id IN (t1.ID, t1.ID2)
)
WHERE rn = 1;
内部选择通过id
或vid
上的简单联接从两个表中获取id
和id2
值。 rank
函数根据startdte
计算第二个表中每个匹配行的排名。你希望在那个日期过滤它有点复杂,所以我使用case
通过将评估值更改为null来有效地忽略今天或稍后的任何日期,在这种情况下,这意味着{{1 <{1}}子句需要order by
,因此忽略它们。
我建议你先自己运行内部选择 - 为简洁起见,可能只需要几个over
值 - 看看它做了什么,以及分配了什么等级。
外部查询只是为每个nulls last
选择排名靠前的结果。
你可能仍会得到重复;如果id
对于具有相同id
的{{1}}有多行,则他们将获得相同的排名,但之后您可能已经遇到过这种情况。您可能需要向table2
添加更多字段,以便以对您有所帮助的方式打破关系。
但这很大程度上是在猜测你现有的查询实际上很慢的原因。