A"不等于"谓词会大大减慢查询速度;我能做些什么呢?

时间:2015-08-28 15:24:45

标签: sql-server sql-server-2008 tsql

我尝试做的是修改现有视图以从视图中排除某些记录。所以我加入了相应的表格,在WHERE子句中,我添加了PSRD.RoleID <> 153,但这使查询从大约15秒钟开始运行超过5分钟。我还尝试在JOIN中移除所有RoleID的153,但这并没有影响运行时间。

建议?

这是SQL:

SELECT
PEVD.EmployeeID [EmployeeID],
P.PersonID,
SEM.eventbegindate [EventDate], 
LEFT (CONVERT (varchar(20), MIN (PSD.StartTime), 108), 5) [StartTime],
LEFT (CONVERT (varchar(20), MAX (PSD.EndTime), 108), 5) [EndTime],
CASE WHEN DAY (MIN (PSD.StartTime)) <> DAY (MAX (PSD.EndTime)) THEN 1 ELSE 0 END [IsAddDay]
FROM
StaffingEventMaster SEM
INNER JOIN StaffingEventShiftDetail SESD on SEM.EventID = SESD.EventID
INNER JOIN PeopleStaffingDetail PSD on SESD.ShiftID = PSD.ShiftID
INNER JOIN People P on PSD.PersonID = P.PersonID
INNER JOIN PeopleEmployeeValueDetail PEVD on PEVD.PersonID =P.PersonID
INNER JOIN PeopleStaffingRoleDetail PSRD on P.PersonID = PSRD.PersonID AND PSRD.RoleID <> 153
LEFT OUTER JOIN SiteMaster SM on SEM.SiteID = SM.SiteID
LEFT OUTER JOIN DriveMaster DM on SEM.DriveID = DM.DriveID
LEFT OUTER JOIN Accounts A on DM.AccountID = A.AccountID
WHERE
--PSRD.RoleID <> 153 and
LEN (PEVD.EmployeeID) > 0
GROUP BY
PEVD.EmployeeID,
P.PersonID,
SEM.EventBeginDate

我已经包含了两个执行计划 - 一个包含&lt;&gt;在WHERE子句和原始。

Execution Plan With <> in Where Clause

Original Query

2 个答案:

答案 0 :(得分:2)

不确定这是否会有所帮助,但看起来有几个表没有使用

SELECT PEVD.EmployeeID [EmployeeID],
       PSD.PersonID,
       SEM.eventbegindate [EventDate], 
       LEFT (CONVERT (varchar(20), MIN (PSD.StartTime), 108), 5) [StartTime],
       LEFT (CONVERT (varchar(20), MAX (PSD.EndTime), 108), 5)   [EndTime],
       CASE WHEN DAY (MIN (PSD.StartTime)) <> DAY (MAX (PSD.EndTime)) THEN 1 ELSE 0 END [IsAddDay]
  FROM StaffingEventMaster SEM
  JOIN StaffingEventShiftDetail SESD 
    on SEM.EventID = SESD.EventID
  JOIN PeopleStaffingDetail PSD 
    on SESD.ShiftID = PSD.ShiftID
  JOIN PeopleEmployeeValueDetail PEVD 
    on PEVD.PersonID = PSD.PersonID
   and LEN (PEVD.EmployeeID) > 0
  JOIN PeopleStaffingRoleDetail PSRD 
    on PSRD.PersonID = PSD.PersonID
   AND PSRD.RoleID <> 153
 GROUP BY PEVD.EmployeeID,
          PSD.PersonID,
          SEM.EventBeginDate

这可能会更快

    SELECT PEVD.EmployeeID [EmployeeID],
           PSD.PersonID,
           SEM.eventbegindate [EventDate], 
           LEFT (CONVERT (varchar(20), MIN (PSD.StartTime), 108), 5) [StartTime],
           LEFT (CONVERT (varchar(20), MAX (PSD.EndTime), 108), 5)   [EndTime],
           CASE WHEN DAY (MIN (PSD.StartTime)) <> DAY (MAX (PSD.EndTime)) THEN 1 ELSE 0 END [IsAddDay]
      FROM StaffingEventMaster SEM
      JOIN StaffingEventShiftDetail SESD 
        on SEM.EventID = SESD.EventID
      JOIN PeopleStaffingDetail PSD 
        on SESD.ShiftID = PSD.ShiftID
      JOIN PeopleEmployeeValueDetail PEVD 
        on PEVD.PersonID = PSD.PersonID
       and LEN (PEVD.EmployeeID) > 0
      JOIN PeopleStaffingRoleDetail PSRD1 
        on PSRD1.PersonID = PSD.PersonID
       AND PSRD1.RoleID < 153
      JOIN PeopleStaffingRoleDetail PSRD2 
        on PSRD2.PersonID = PSD.PersonID
       AND PSRD2.RoleID > 153
     GROUP BY PEVD.EmployeeID,
              PSD.PersonID,
              SEM.EventBeginDate

答案 1 :(得分:1)

我建议尝试NOT (PSRD.RoleID = 153)并且似​​乎没有理由让3个左连接表格。我也想知道这个测试LEN(PEVD.EmployeeID) > 0是否真的需要;你真的在这样的领域有零长度的字符串吗?

SELECT
      PEVD.EmployeeID [EmployeeID]
    , P.PersonID
    , SEM.eventbegindate [EventDate]
    , LEFT(CONVERT(varchar(20), MIN(PSD.StartTime), 108), 5) [StartTime]
    , LEFT(CONVERT(varchar(20), MAX(PSD.EndTime), 108), 5) [EndTime]
    , CASE
            WHEN DAY(MIN(PSD.StartTime)) <> DAY(MAX(PSD.EndTime)) THEN 1
            ELSE 0
      END [IsAddDay]
FROM StaffingEventMaster SEM
      INNER JOIN StaffingEventShiftDetail SESD ON SEM.EventID = SESD.EventID
      INNER JOIN PeopleStaffingDetail PSD ON SESD.ShiftID = PSD.ShiftID
      INNER JOIN People P ON PSD.PersonID = P.PersonID
      INNER JOIN PeopleEmployeeValueDetail PEVD ON PEVD.PersonID = P.PersonID
      INNER JOIN PeopleStaffingRoleDetail PSRD ON P.PersonID = PSRD.PersonID
      /*
      LEFT OUTER JOIN SiteMaster SM ON SEM.SiteID = SM.SiteID
      LEFT OUTER JOIN DriveMaster DM ON SEM.DriveID = DM.DriveID
      LEFT OUTER JOIN Accounts A ON DM.AccountID = A.AccountID
      */
WHERE NOT (PSRD.RoleID = 153)
      /* AND LEN(PEVD.EmployeeID) > 0 suggest you replace this line */
      AND PEVD.EmployeeID IS NOT NULL
GROUP BY
      PEVD.EmployeeID
    , P.PersonID
    , SEM.eventbegindate