我有一个查询,需要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部分实际上正在减慢速度。当我删除这个连接时,它的工作速度非常快,但结果集不是早期的结果。(它返回更多数据)
AND (UGL.FK_lngGroupID = MSL.FK_lngGroupID
OR UGL.FK_lngGroupID = 2)
如果您能够显示优化查询或某些示例或其他编写相同查询的方法,我将非常感激。
答案 0 :(得分: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;
另一方面,请注意,NOLOCK
和READ_UNCOMMITTED
隔离级别可能会导致在分配顺序扫描期间跳过或重复行,如果在查询运行时更新数据。只有在并发性比正确结果更重要时才应使用脏读。
答案 1 :(得分:0)
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