2017-08-27 77 views
0

我有一個需要1分鐘執行的查詢。在查詢中花費了一些時間之後,我發現有一部分實際上導致查詢耗費時間。 請在下面查看我提出的查詢的意見。如何提高多個內部聯接的查詢性能?

完整的查詢:

SELECT DISTINCT 
    CSU.*, U.txtFirstName, U.txtLastName 
FROM 
    tblCRMShallowUsers CSU (NOLOCK) 
INNER JOIN 
    tblUsers U (NOLOCK) ON CSU.PK_autUserID = U.PK_autUserID 
INNER JOIN 
    tblUserGroupLink UGL (NOLOCK) ON U.PK_autUserID = UGL.FK_lngUsersID 
INNER JOIN 
    tblModuleSecurityLinks MSL (NOLOCK) ON FK_lngModuleID = 28 
INNER JOIN 
    tblGroups G (NOLOCK) ON G.PK_autGroupID = MSL.FK_lngGroupID 
WHERE 
    MSL.lngRights > 0 
    AND U.lngStatus > 19 
    AND U.ysnAdminFlag = 0 
    AND G.lngStatus > 19 
    AND G.ysnFrontEndGroup = 0 
    AND (UGL.FK_lngGroupID = MSL.FK_lngGroupID 
     OR UGL.FK_lngGroupID = 2) 
ORDER BY 
    ysnHasAccess DESC, txtLastName, txtFirstName 

下面聯接在上面的查詢快速執行:

INNER JOIN 
    tblUsers U (NOLOCK) ON CSU.PK_autUserID = U.PK_autUserID 
INNER JOIN 
    tblUserGroupLink UGL (NOLOCK) ON U.PK_autUserID = UGL.FK_lngUsersID 
INNER JOIN 
    tblModuleSecurityLinks MSL (NOLOCK) ON FK_lngModuleID = 28 
INNER JOIN 
    tblGroups G (NOLOCK) ON G.PK_autGroupID = MSL.FK_lngGroupID 

這裏的及部分在真的減緩下來上面的查詢。當我刪除這個連接,它正在非常快,但結果集是不是更早到來的結果。(返回更多的數據)

AND (UGL.FK_lngGroupID = MSL.FK_lngGroupID 
    OR UGL.FK_lngGroupID = 2) 

我真的很感激,如果你能表現出一定的方向,以優化查詢或者編寫相同查詢的一些示例或其他方式。

+0

您是否嘗試過加入適量的索引到你的表? –

+1

集[壞習慣踢 - 把NOLOCK到處(http://blogs.sqlsentry.com/aaronbertrand/bad-habits-nolock-everywhere/) - 是*不推薦*到處使用這個 - 恰恰相反! –

+0

https://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-a-very-simple-sql-query即在代碼中添加一些'create ...'和'insert ...'行,爲測試和演示奠定基礎。 – Yunnosch

回答

0

因爲每個OR謂詞的最佳執行計劃都不相同,所以通過將單個查詢重構爲單獨的SELECT查詢和UNION運算符,可以提高性能。這允許優化器爲每個查詢獨立選擇最佳計劃。 DISTINCT不需要,因爲UNION從結果中刪除重複的行。

SELECT 
    CSU.*, U.txtFirstName, U.txtLastName 
FROM 
    tblCRMShallowUsers CSU (NOLOCK) 
INNER JOIN 
    tblUsers U (NOLOCK) ON CSU.PK_autUserID = U.PK_autUserID 
INNER JOIN 
    tblUserGroupLink UGL (NOLOCK) ON U.PK_autUserID = UGL.FK_lngUsersID 
INNER JOIN 
    tblModuleSecurityLinks MSL (NOLOCK) ON FK_lngModuleID = 28 
INNER JOIN 
    tblGroups G (NOLOCK) ON G.PK_autGroupID = MSL.FK_lngGroupID 
WHERE 
    MSL.lngRights > 0 
    AND U.lngStatus > 19 
    AND U.ysnAdminFlag = 0 
    AND G.lngStatus > 19 
    AND G.ysnFrontEndGroup = 0 
    AND UGL.FK_lngGroupID = MSL.FK_lngGroupID 
UNION 
SELECT 
    CSU.*, U.txtFirstName, U.txtLastName 
FROM 
    tblCRMShallowUsers CSU (NOLOCK) 
INNER JOIN 
    tblUsers U (NOLOCK) ON CSU.PK_autUserID = U.PK_autUserID 
INNER JOIN 
    tblUserGroupLink UGL (NOLOCK) ON U.PK_autUserID = UGL.FK_lngUsersID 
INNER JOIN 
    tblModuleSecurityLinks MSL (NOLOCK) ON FK_lngModuleID = 28 
INNER JOIN 
    tblGroups G (NOLOCK) ON G.PK_autGroupID = MSL.FK_lngGroupID 
WHERE 
    MSL.lngRights > 0 
    AND U.lngStatus > 19 
    AND U.ysnAdminFlag = 0 
    AND G.lngStatus > 19 
    AND G.ysnFrontEndGroup = 0 
    AND UGL.FK_lngGroupID = 2 
ORDER BY 
    ysnHasAccess DESC, txtLastName, txtFirstName; 

在一個側面說明,要知道比NOLOCKREAD_UNCOMMITTED隔離級別可能導致跳過或在分配順序掃描複製行如果查詢運行時數據被更新。髒讀只能在併發比正確結果更重要時使用。

0

@DanGuzman @flaschenpost我也與CTE的方式試圖分割拼接爲2分seaprate的東西,但它不工作,並採取相同的時間,因爲它是(1分鐘)。 你可以看看我試過的下面的查詢。

  1. 隨着CTE方法:With UsersUserGroupLink AS( Select U.PK_autUserID, U.txtFirstName, U.txtLastName, U.lngStatus, U.ysnAdminFlag, UGL.FK_lngGroupID FROM tblUsers as U (NOLOCK) INNER JOIN tblUserGroupLink as UGL (NOLOCK) ON U.PK_autUserID = UGL.FK_lngUsersID ), GroupsModuleSecurityLinks AS(Select MSL.lngRights, G.lngStatus, G.ysnFrontEndGroup, MSL.FK_lngGroupID From
    tblModuleSecurityLinks as MSL (NOLOCK) INNER JOIN tblGroups as G (NOLOCK) ON G.PK_autGroupID = MSL.FK_lngGroupID AND MSL.FK_lngModuleID = 28 ) (SELECT DISTINCT CSU.*, UsersUserGroupLink.txtFirstName, UsersUserGroupLink.txtLastName FROM UsersUserGroupLink Inner join
    tblCRMShallowUsers as CSU ON UsersUserGroupLink.PK_autUserID =
    CSU.PK_autUserID Inner join GroupsModuleSecurityLinks ON
    GroupsModuleSecurityLinks.FK_lngGroupID =
    UsersUserGroupLink.FK_lngGroupID or UsersUserGroupLink.FK_lngGroupID = 2 WHERE GroupsModuleSecurityLinks.lngRights > 0 AND UsersUserGroupLink.lngStatus > 19 AND UsersUserGroupLink.ysnAdminFlag = 0 AND GroupsModuleSecurityLinks.lngStatus > 19 AND GroupsModuleSecurityLinks.ysnFrontEndGroup = 0) ORDER BY ysnHasAccess DESC, txtLastName, txtFirstName