我有这个SQL查询,我在java中运行JDO:
SELECT idPath, token, isTV, rel
FROM path
LEFT OUTER JOIN relation ON (path.idTokenN=relation.idTokenN)
WHERE path.idPath IN( SELECT DISTINCT path.idPath
FROM path
WHERE path.isTV='true'
)
AND path.idPath IN( SELECT DISTINCT path.idPath
FROM path
GROUP BY path.idPath
HAVING COUNT(*) >= 2 AND COUNT(*) <= 3
)
要运行它需要大约3个小时,我该如何减少执行时间?
修改
使用MySQL DBMS
路径表:
idTokenN idPath token isTV
1 p1 test1 true
2 p1 test2 false
3 p2 test3 true
4 p3 test4 false
5 p3 test5 false
6 p4 test6 false
7 p4 test7 true
8 p4 test8 false
9 p4 test9 false
10 p5 test10 true
11 p5 test11 false
12 p5 test12 false
关系表:
idTokenN idTokenN2 rel
10 11 test
当然,我的数据库中的数据很多,这只是一个例子!
答案 0 :(得分:2)
优化查询取决于几个因素。最重要的是数据库引擎。第二个是数据的特征。您的问题提供了有关这两者的信息。
一个非常重要的信息是两个表的大小,每个表中的行数,以及每个表中idTokenN
的不同值的数量。 left outer join
很可能正在确定查询的性能特征。
您可以做的第一件事就是删除distinct
关键字。 in
子查询中从不需要这样做,有些数据库引擎可能不会忽略它。
优化查询的另一个步骤是删除in
子查询。在某些数据库中,这些数据不能很好地优化。它们可以由join
和聚合子查询替换:
SELECT p.idPath, p.token, p.isTV, r.rel
FROM path p LEFT OUTER JOIN
relation r
ON p.idTokenN = r.idTokenN JOIN
(select idPath, max(case when p.isTV = 'true' then 1 else 0 end) as HasTv,
(case when COUNT(*) between 2 and 3 then 1 else 0 end) as Has2_3
from path p
group by idpath
) pf
on p.idpath = pf.idpath and
pf.HasTv = 1 and pf.Has2_3 = 1;
您肯定可以做其他事情,但除此之外,它们还会依赖于数据库。