2011-10-18 51 views
0

任何人都知道我可以如何優化這個查詢?它可以工作,但需要很長時間纔會導致服務器超時。mysql大查詢性能改進

$screenRestrict="clientID='1' AND screenID='1'"; 
$lastupdate="1318515710"; 

INSERT INTO allvisits (clientID, screenID, hitID, entryPageID, entryPageName, xentryTime, xexitTime, pagecount, minsonsite)(
    SELECT 
     clientID, screenID, id AS hitID, pageID AS entryPageID, 
     (SELECT name FROM pages WHERE id=entryPageID) AS entryPageName, 
     (SELECT clicktime FROM clicks WHERE id = hitID AND isFirstClick=1) AS xentryTime, 
     (SELECT MIN(clicktime) FROM clicks WHERE $screenRestrict AND isLastClick=1 AND clicktime > xentryTime) AS xexitTime, 
     (SELECT COUNT(*) FROM clicks WHERE $screenRestrict AND clicktime BETWEEN xentryTime AND xexitTime) AS pagecount, 
     (SELECT (xexitTime-xentryTime)/60) AS minsonsite 
    FROM clicks WHERE $screenRestrict AND isFirstClick=1 AND clicktime>'$lastupdate' 
) 

感謝很多:)

更新:

感謝所有的提示。我已經爲isLastClick添加了一個索引,並且設法加快了它的速度,但是在低服務器負載下它仍然需要+10秒。我已經確定了最後一個瓶頸,並在下面標記了它。有沒有更好的方法來選擇晚於xentrytime的第一個「isLastClick」記錄?

SELECT clientid, 
      screenid, 
      id              AS hitid, 
      pageid             AS entrypageid, 
      clicktime            AS xentrytime, 
      (SELECT name 
       FROM pages 
       WHERE id = entrypageid)        AS entrypagename, 
      (SELECT clicktime 
       FROM clicks 
       WHERE clicktime > xentrytime //<<removing this cuts 8.5 seconds!! 
          AND screenid = '2' 
          AND islastclick = 1 
          LIMIT 1)    AS xexittime, 
      (SELECT COUNT(1) 
       FROM clicks 
       WHERE screenid = '2' 
          AND clicktime BETWEEN xentrytime AND xexittime) AS pagecount, 
      (SELECT (xexittime - xentrytime)/60)    AS minsonsite 
FROM clicks 
WHERE screenid = '2' 
      AND isfirstclick = 1 
      AND clicktime > '1318961057' 
+4

首先,您應該針對每個選擇的查詢運行'explain'來了解可能存在性能問題的位置。並檢查索引。 – user973254

+0

嘗試將索引添加到您查詢的列中? –

+0

酷不知道「解釋」 - 我會看看它。所有「ID」列都是主鍵。我不認爲點擊表中有任何其他獨特的數據,所以我不知道有什麼方法可以添加索引? – cronoklee

回答

1

請檢查評論。

if $ screenrestrict和page id對於一個頁面是相同的。嘗試加入內部表與該頁面ID

我不確定你對xentrytime和xexittime列的想法。因爲,我看到使用子查詢爲同一事物獲取feilds。

只要記住,爲了調整查詢,嘗試獲取過濾器並限制在每個子查詢中選擇的行數。有些過濾器是基於業務邏輯編寫的,所以當你寫一個查詢時,考慮包括這些條件,並看看解釋計劃中的性能是否提高。

INSERT INTO allvisits 
      (clientid, 
      screenid, 
      hitid, 
      entrypageid, 
      entrypagename, 
      xentrytime, 
      xexittime, 
      pagecount, 
      minsonsite) 
(SELECT clientid, 
     screenid, 
     id              AS hitid, 
     pageid             AS entrypageid, 
     (SELECT name 
     FROM pages 
     WHERE id = entrypageid)        AS entrypagename 
     , 
     clicktime      AS xentrytime, //this should work w.r.t your code 
     (SELECT MIN(clicktime)    //try to change this logic. The logic written here doesnt look good at all. and try to filter out data by joining with outer table. 
     FROM clicks 
     WHERE $screenrestrict 
       AND islastclick = 1 
       AND clicktime > xentrytime)      AS xexittime, 
     (SELECT COUNT(1) //this will give some performance improvement 
     FROM clicks 
     WHERE $screenrestrict 
       AND clicktime BETWEEN xentrytime AND xexittime) AS pagecount, 
     (SELECT (xexittime - xentrytime)/60)    AS minsonsite 
FROM clicks 
WHERE $screenrestrict 
     AND isfirstclick = 1 
     AND clicktime > '$lastupdate') 

更新

這2次內的查詢需要更多的微調

 SELECT MIN(innClick.clicktime)    
     FROM clicks innClick1 
     WHERE innClick1.screenid = '2' // when u put it as part of big query use WHERE innClick1.screenid = outClick.screenid instead of hard coding it. where outClick is alias for Click table in outside 
       AND innClick1.islastclick = 1 
       AND innClick1.clicktime > innClick1.xentrytime 

     SELECT COUNT(1) 
     FROM clicks innClick2 
     WHERE innClick2.screenid = '2' 
       AND innClick2.clicktime BETWEEN innClick2.xentrytime AND innClick2.xexittime 

WRT解釋計劃

  • 你可以嘗試添加更多的過濾器,以減少數量在內部查詢中獲取的行。
  • 嘗試減少任何全表掃描,並且如果掃描基於索引掃描(全部也是),則暫時可以忽略。
  • 嘗試基於已編制索引的列添加過濾器。
  • 嘗試通過在這些子查詢中進一步篩選數據來進行大量試驗和錯誤,並嘗試分別減少每個查詢中的時間。然後最終加入他們,當你有更好的性能

clicktime,xentrytime和xexittime如果索引將會更好的性能爲查詢我猜。你可以試試,but still indexing will slow your insert statements,因爲每次插入時都應該更新這些額外的索引。

+0

嘿,非常感謝巴布!我已經發布了有關您的提示的更新。我該如何去加入到外部桌子並保持準確的結果? – cronoklee