0
SELECT projectID, urlID, COUNT(1) AS totalClicks, projectPage, 
    (SELECT COUNT(1) 
    FROM tblStatSessionRoutes, tblStatSessions 
    WHERE tblStatSessionRoutes.statSessionID = tblStatSessions.ID 
    AND tblStatSessions.projectID = tblAdClicks.projectID 
    AND (tblStatSessionRoutes.leftPageID = tblAdClicks.projectPage OR 
      tblStatSessionRoutes.rightPageID = tblAdClicks.projectPage)) AS totalViews 
    FROM tblAdClicks 
    WHERE projectID IN (SELECT projectID FROM tblProjects WHERE userID = 5) 
    GROUP BY projectID, urlID, projectPage 
    ORDER BY CASE projectID 
      WHEN 170 THEN 
      1 
      ELSE 
      0 
     END, projectID 

這絕不是一個特別複雜的查詢,但因爲數據庫是歸到一個較好的水平,我們正在處理的數據的顯著量,這種查詢可以是相當緩慢用戶。運行SQL查詢更快

有沒有人有提示如何提高它的速度?如果我戰略性地對數據庫的某些部分進行非規範化,這會有幫助嗎?在存儲過程中運行它會提供顯着的改進嗎?

我在我的代碼中處理數據的方式非常有效,瓶頸實際上就是這個查詢。

謝謝!

+0

您使用的是什麼RDBMS? MySQL,SQL Server,Postgres? – 2011-01-06 12:06:17

+0

SQL-Server就是這樣運行的。只有v2000有點垃圾! – 2011-01-06 12:08:07

回答

3

德正常化您的數據庫應該是最後的手段,因爲(選擇只有一個原因),你不希望(與GROUP BY幫助)鼓勵去規範化將允許的數據不一致。

首先要看你是否可以從查詢執行計劃中獲得一些線索。例如,它可能是您的子選擇成本太高,並且最好先進入臨時表,然後在主查詢中加入。此外,如果您看到很多表掃描,您可以從改進的索引中受益。

如果你還沒有,你應該花幾分鐘重新格式化您的查詢的可讀性。這很明顯,在這樣做的時候,明顯的優化會跳出你的頻率。

3

我會嘗試向上突破該

projectID IN (SELECT projectID FROM tblProjects WHERE userID = 5) 

,並改爲使用JOIN:

SELECT 
    projectID, urlID, COUNT(1) AS totalClicks, projectPage, 
    (SELECT COUNT(1) ....) AS totalViews 
FROM 
    dbo.tblAdClicks a 
INNER JOIN 
    dbo.tblProjects p ON a.ProjectID = p.ProjectID 
WHERE 
    p.UserID = 5 
GROUP BY 
    a.projectID, a.urlID, a.projectPage 
ORDER BY 
    CASE a.projectID 
     WHEN 170 THEN 1 
     ELSE 0 
    END, a.projectID 

不知道到底有多少,這將幫助 - 應該有點幫助,我希望!

除此之外,我會檢查您是否在相關列上有索引,例如在a.ProjectID(幫助與JOIN),也許對a.urlIDa.ProjectPage

1

如果您的dbms有一個解釋其查詢計劃的工具,請首先使用它。 (您的第一個相關子查詢可能每行運行一次)。確保每個在WHERE子句中引用的列都有一個索引。

這個子查詢 - WHERE projectID IN(SELECT projectID FROM tblProjects WHERE userID = 5) - 肯定可以受益於被剪切並作爲視圖實現。然後加入視圖。

將點擊流數據視爲數據倉庫應用程序並不罕見。如果你需要走這條路線,我通常會實施一個單獨的數據倉庫,而不是對設計良好的OLTP數據庫進行規範化。

我懷疑將它作爲存儲過程運行會對您有所幫助。

1

我會嘗試刪除相關子查詢(內部(SELECT COUNT(1) ...))。必須加入會議路線,左頁或右頁匹配會使事情變得有點棘手。沿線的東西(但我沒有測試過這一點):

SELECT tblAdClicks.projectID, tblAdClicks.urlID, COUNT(1) AS totalClicks, tblAdClicks.projectPage, 
     SUM(CASE WHEN leftRoute.statSessionID IS NOT NULL OR rightRoute.statSessionID IS NOT NULL THEN 1 ELSE 0 END) AS totalViews 
FROM tblAdClicks 
    JOIN tblProjects ON tblProjects.projectID = tblAdClicks.projectID 
    LEFT JOIN tblStatSessions ON tblStatSessions.projectID = tblAdClicks.projectID 
    LEFT JOIN tblStatSessionRoutes leftRoute ON leftRoute.statSessionID = tblStatSessions.ID AND leftRoute.leftPageID = tblAdClicks.projectPage 
    LEFT JOIN tblStatSessionRoutes rightRoute ON rightRoute.statSessionID = tblStatSessions.ID AND rightRoute.rightPageID = tblAdClicks.projectPage 
WHERE tblProjects.userID = 5 
GROUP BY tblAdClicks.projectID, tblAdClicks.urlID, tblAdClicks.projectPage 
ORDER BY CASE tblAdClicks.projectID WHEN 170 THEN 1 ELSE 0 END, tblAdClicks.projectID 

如果我要添加一些緩存表,以幫助這一點,因爲我指出我會盡量減少對tblStatSessionRoutes同時爲兩個查詢左右頁面爲單個查詢。例如,如果您知道leftPageID永遠不會等於rightPageID,那麼應該可以簡單地使用觸發器將單獨行中的左視圖和右視圖填充到附加表中。