提高SQL查询执行速度

时间:2014-03-28 10:49:50

标签: java sql jdo

我有这个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

当然,我的数据库中的数据很多,这只是一个例子!

1 个答案:

答案 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;

您肯定可以做其他事情,但除此之外,它们还会依赖于数据库。