需要特定的SQL查询优化帮助

时间:2011-03-14 21:31:48

标签: mysql sql query-optimization

所以我正在开展一个数据挖掘项目,我们正在研究代码元素及其与这些事物的关系和变化。我们想要的是询问一些关于相关元素改变频率的问题。我已将其设置为视图,但运行时间为10分钟。我认为问题在于我必须进行大量的减法,连接和字符串比较来比较条目(对于我们的窗口大小),但我不知道解决这个问题的好方法。查询看起来像

select aw.same
     , rw.k
     , count(distint concat_ws(',', r1.id, r2.id)) as num  
  from deltamethoddeclaration dmd1
    join revision r1
      on r1.id=FKrevID 
    join methodinvocation mi
      on mi.FKcallerID = dmd1.FKMDID 
    join deltamethoddeclaration dmd2 
      on mi.FKcalleeID = dmd2.FKMDID
    join revision r2 
      on r2.id = dmd2.FKrevID
    join revisionwindow rw
    join authorwindow aw
  where (dmd1.FKrevID - dmd2.FKrevID) < rw.k
    and (dmd2.FKrevID - dmd1.FKrevID) < rw.k
    and case aw.same
          when 1 then
            r1.author = r2.author
          when 0 then
            r1.author <> r2.author
          else
            1=1
         end
  group by aw.same
         , rw.k
;

好的,所以revisionwindow存储了我们感兴趣的修订版窗口(10,20,50,100),并且作者窗口存储了我们想要的作者类型(相同,不同,不关心)。问题的一部分是,我们可以使用不同元素匹配的相同修订对,因此我能想到的唯一的黑客就是丑陋的计数(不同的concat())。这应该返回一个包含12行的表,每个表对应一个作者和修订版窗口的组合。 'num'下的条目是以指定方式相关的唯一修订对(在这种情况下,两种更改方法和一种方法都调用另一种)。它工作得很好,它只是疯狂的慢(约10分钟的运行时间)。我基本上都在寻求任何建议或帮助,以便在不牺牲准确性的情况下使这项工作更好。

2 个答案:

答案 0 :(得分:1)

  •   

    其中(dmd1.FKrevID-dmd2.FKrevID)&lt; rw.k

    对此语句最具破坏性的是小于运算符<而不是算术运算。 B树不能使用它,并且每次都会强制进行全表扫描。 Gory详细说明了为什么这样做:http://explainextended.com/2010/05/19/things-sql-needs-determining-range-cardinality/

  • 我怀疑后端可以优化您的CASE语句,<>运算符会遇到与上述相同的问题。我会考虑加入=运算符的方法,可能会破坏查询并使用UNION语句,因此您始终可以使用索引。

  • 您没有使用EXPLAIN。您需要开始使用它来优化查询。您不知道正在使用哪些索引,哪些索引没有使用,或者您的条件是否具有足够的选择性甚至是有用的(如果它不是非常有选择性,请参阅最后一点)http://dev.mysql.com/doc/refman/5.0/en/explain.html

  • 由于这是一个数据挖掘应用程序,因此您有很好的机会使用中间值的临时表。由于数据可能会定期(甚至可能只有一次!)进行转储,因此很容易经常重建长时间运行的临时表,而不会冒数据损坏的风险(或者因为您在寻找聚合模式时无关紧要) 。)

    我已经开始运行超过60分钟的查询,并通过构建缓存硬件的临时表将它们减少到不到100毫秒(即时)。如果你不能使用上面的任何一个想法,这可能是最低的水果。采取所有'硬件' - 案例连接和非平等连接,并在一个地方做。然后在你的临时表中添加一个索引:-)诀窍是让它足够通用,你可以查询临时表,这样你仍然可以灵活地提出不同的问题。

答案 1 :(得分:0)

我怀疑两个连接(join revisionwindow rw)和(join authorwindow aw)没有ON条件但是使用WHERE,导致这个。

这两张表有多少条记录? MySQL可能首先在这些上进行CROSS JOIN,然后才检查复杂(WHERE)条件。

但请发布EXPLAIN的结果。

- EDIT--
哎呀,我错过了你的最后一段,解释说这两个表有4行和3行。

你可以试试这个: (已取代concat的地方 并且where子句已被移动为JOIN ON ...)

select aw.same
     , rw.k
     , count(distint r1.id, r2.id) as num  
  from deltamethoddeclaration dmd1
    join revision r1
      on r1.id = dmd1.FKrevID 
    join methodinvocation mi
      on mi.FKcallerID = dmd1.FKMDID 
    join deltamethoddeclaration dmd2 
      on mi.FKcalleeID = dmd2.FKMDID
    join revision r2 
      on r2.id = dmd2.FKrevID
    join revisionwindow rw
      on (dmd1.FKrevID - dmd2.FKrevID) < rw.k
         and (dmd2.FKrevID - dmd1.FKrevID) < rw.k
    join authorwindow aw
      on case aw.same
           when 1 then
             r1.author = r2.author
           when 0 then
             r1.author <> r2.author
           else
             1=1
          end
  group by aw.same
         , rw.k
;