2011-03-14 51 views
0

因此,我正在研究一個數據挖掘項目,我們正在查看代碼元素及其關係,並隨着時間的推移對這些內容進行更改。我們想要問的是關於相關元素多久更換一次的問題。我已經將它設置爲一個視圖,但它需要運行10分鐘。我相信問題是我不得不做很多減法,串聯和字符串比較來比較條目(對於我們的窗口大小),但我不知道解決這個問題的好方法。查詢看起來像需要特定的SQL查詢優化幫助

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)和authorwindow存儲了筆者類型,我們想要的(相同,不同的,也不要關心)。部分問題是,我們可能會有不同的元素匹配的修訂版本,所以我唯一能想到的就是那個醜陋的數字(獨特的concat())。這應該返回一個有12行的表,每個作者和修訂版窗口的組合都有一個表。 'num'下的條目是以指定方式相關的唯一修訂對(在這種情況下,兩個修改方法和一個方法都會調用另一個)。它完美的工作,它只是瘋狂的慢(約10分鐘的運行時間)。我基本上都在尋找任何建議或幫助在不犧牲準確性的情況下更好地完成這項工作。

+0

您是否擁有所有主鍵/外鍵的索引?每個表中有多少行? –

+0

'methodinvocation'中有多少條記錄? – Quassnoi

+0

所有的鍵都被編入索引。方法表中有大約110K條目。 deltamethoddeclaration有120K條目,修訂有14K –

回答

0

我懷疑沒有ON條件但使用WHERE的兩個連接(join revisionwindow rw)和(join authorwindow aw)導致這種情況。

這兩個表有多少條記錄? MySQL可能首先會對這些進行CROSS JOIN,然後纔會檢查複雜(WHERE)條件。

但請發佈EXPLAIN的結果。

- EDIT--
糟糕,我錯過了最後一段,它解釋了兩個表格有4行和3行。

你可以試試這個: (其中CONCAT已取代 和where子句已經被移動的加入就......)

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 
; 
1
  • 其中(dmd1.FKrevID - dmd2.FKrevID)< rw.k

    的最具破壞性的這個說法是小於運算符<試驗時他算術。 B樹不能使用它,並隨時強制進行全表掃描。血淋淋的細節,爲什麼這是真的: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毫秒(即時)。如果你不能使用上述任何想法,這可能是最低級的成果。採取所有'困難的東西' - 案例連接和非平等連接,並將它做到一個地方。然後給你的臨時表添加一個索引:-)訣竅是使它足夠通用,以便查詢臨時表,這樣你仍然可以靈活地提出不同的問題。

+0

nate,謝謝你的評論。很明顯,我之前沒有這樣做過,所以你能給我一個更具體的指針來解決這個問題嗎?由於它減去兩個鍵,我仍然可以使用第一個鏈接中討論的範圍技巧嗎?或者你能給我一個例子,說明如何放置臨時表以及如何使用它? –

+0

@Kyle:假設你可以使用預先計算的索引,但在這種情況下它不起作用,因爲它們只能使用來自一個表(不是自聯接)的常量和值。它可能是一個很好的候選人創建一個臨時表,然後添加索引。 –

+0

@Kyle:不確定索引是否是你的主要問題,因爲它看起來好像你沒有太多的選擇性掃描大多數行。不管你做什麼,都可能導致全表掃描。我會認真考慮使用ID和ID作者的大小寫表達式的差異來預先計算臨時表。如果您可以預先彙總數據,那麼您可能會使查詢運行得非常快。然後用修訂版和作者窗口的東西查詢臨時表。 –