2014-01-22 38 views
0

我希望有人可以看看我的查詢下面請。我在運行的網站上遇到了一些CPU問題,這會在高峯時段降低網站速度。SQL查詢優化/整理有問題的查詢

當用戶註冊時,系統從一個包含180萬行的Postcode表中選擇Easting和Northing值,我在這個表上設置了一個索引,並且認爲它的運行和我可能的一樣,但是我也有另一個查詢當我在執行計劃中查看時,這顯示出相當高的成本(某些部分爲28%)。

以下查詢選擇帳戶詳細信息,用戶星級評分的平均值,還使用計算登錄用戶與所有結果之間的里程以顯示最近的第一個的功能。

你可以看到任何明顯錯誤的方式,我把它放在一起,我的SQL是好的,但有限,所以將不勝感激任何幫助,因爲它是一個長期運行的問題。

SELECT tblAccounts.accountID , 
     tblAccounts.city , 
     tblAccounts.emailAddress , 
     tblAccounts.paypalEmailAddress , 
     tblAccounts.skypeUsername , 
     tblAccounts.EA , 
     tblAccounts.postcode , 
     [onlineBootyUser].[fn_radialDistance](tblAccounts.EA, tblAccounts.NO, 
               @EA, @NO) AS miles , 
     tblOrders.tableclothVisible , 
     (SELECT AVG(starRating) AS averageRating 
      FROM  onlinebootyUser.tblStarRating 
      WHERE  (accountID = onlinebootyUser.tblOrders.accountID) 
     ) AS starRating 
FROM tblOrders 
     INNER JOIN tblAccounts ON tblOrders.accountID = tblAccounts.accountID 
WHERE (tblAccounts.valid = 1) 
     AND ((tblOrders.orderStatus = 'Completed') 
       OR (tblOrders.orderStatus = 'Pending') 
      ) 
     AND tblOrders.bootsaleDate = @bootsaleDate 
     AND tblOrders.itemsAllowed > 0 
     AND (SELECT COUNT(*) 
       FROM  tblItems 
       WHERE  tblItems.accountID = tblAccounts.accountID 
         AND tblItems.bootsaleDate = @bootSaleDate 
      ) > 0 
ORDER BY miles ASC 

功能fn_radialDistance如下:

declare @d float; 

     set @d = power(square(@[email protected])+square(@[email protected]),0.5E)/1609.0E 

     return @d 

爲尋找謝謝!

+0

將子查詢移動到2個獨立的CROSS APPLY中可能是值得的。計數(*)將非常繁重,必須對源表中的每一行進行比較。 – TTeeple

+0

你可以分享執行計劃嗎?看到這將有很大幫助。 – steoleary

+0

不太清楚您希望看到的計劃的哪一部分,這是整體視圖... http://imageshack.com/a/img541/4745/24kp.png –

回答

1

這裏是你的查詢格式,所以我可以讀取它:

SELECT a.accountID, a.city, a.emailAddress, a.paypalEmailAddress, a.skypeUsername, a.EA, 
     a.postcode, 
     [onlineBootyUser].[fn_radialDistance](tblAccounts.EA, a.NO, @EA, @NO) AS miles, 
     o.tableclothVisible, 
     (SELECT AVG(starRating) AS averageRating 
     FROM onlinebootyUser.tblStarRating sr 
     WHERE sr.accountID = o.accountID 
     ) AS starRating 
FROM tblOrders o INNER JOIN 
    tblAccounts a 
    ON o.accountID = a.accountID 
WHERE (a.valid = 1) AND (o.orderStatus in ('Completed', 'Pending')) AND 
     o.bootsaleDate = @bootsaleDate AND o.itemsAllowed > 0 AND 
     (SELECT count(*) 
     FROM tblItems i 
     WHERE i.accountID = a.accountID AND i.bootsaleDate = @bootSaleDate 
    ) > 0 
ORDER BY miles ASC 

即出現是你有什麼指標的問題。下面的指標應該有所幫助:

tblItems(accountID, bootsaleDate); 
tblStarRating(accountID, starRating); 

您可以在where更高效的子查詢用exists替換它:

exists (select 1 
     from tblItems i 
     where i.accountID = a.accountID and i.bootsaleDate = @bootSaleDate 
    ) 

這可能是一個小規模的改善,除非匹配的數量是相當高。

除此之外,你會提供一個執行計劃。函數調用很可能會傷害性能。

+0

我只有tblItems和accountID上的accountID,tblOrders上的orderDate。 這些是由執行計劃建議的 –

+0

我提到的索引是針對子查詢的。那些你看起來合理的,但我會傾向於'tblOrders(bootSaleDate,OrderStatus,AccountId)'。 –