2016-08-11 50 views
0

我有以下查詢匹配基於Booking和SMSConfiguration中的CategoryId的記錄。將條件移出聯接,因爲查詢速度慢

這裏我需要找到SMSConfiguration中的NULL CategoryId的記錄。我得到了我的預期產出。但查詢運行2分鐘。

如果我在JOIN中刪除附加條件OR SMS.CategoryId IS NULL,則運行速度會更快,並且會少於1秒。我不知道如何移出JOIN。

SELECT SMS.Id AS ConfigId 
    ,B.BookingId AS BookingId 
    ,B.StartTime AS BookingStartTime 
    ,B.EndTime AS BookingEndTime 
    ,B.BookingDate AS BookingDate 
    ,B.Price AS Price 

FROM Booking B 
INNER JOIN SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId 
    OR SMS.CategoryId IS NULL -- CAUSING SLOW 
    AND SMS.TenantId = B.TenantId 

編輯:

完整的查詢

DECLARE @CurrentDateTime SMALLDATETIME 

SET @CurrentDateTime='2016-08-11 08:00:00.247' 

SELECT SMS.Id AS ConfigId 
     ,B.BookingId AS BookingId 
     ,B.StartTime AS BookingStartTime 
     ,B.EndTime AS BookingEndTime 
     ,B.BookingDate AS BookingDate 
     ,B.Price AS Price 
     ,C.CategoryName AS CategoryName 
     ,PER.PersonId AS PersonId 
     ,P.PatientId AS PatientId 
     ,PER.FirstName AS PatientFirstName 
     ,PER.LastName AS PatientLastName 
     ,PER.MobileNumber AS PatientMobileNumber 
     ,RP.FirstName AS DoctorFirstName 
     ,RP.LastName AS DoctorLastName 
     ,SMS.SMSText 
     ,B.TenantId AS TenantId 
    FROM Booking B 
    INNER JOIN SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId 
     OR SMS.CategoryId IS NULL 
     AND SMS.TenantId = B.TenantId 
    INNER JOIN Tenant T ON T.TenantId = B.TenantId --AND T.IsSMSEnabled=1   
    INNER JOIN Patient P ON B.PatientId = P.PatientId 
    INNER JOIN Person PER ON P.PersonId = PER.PersonId 
    INNER JOIN Person RP ON RP.PersonId = B.ResponsiblePersonId 
    LEFT JOIN Category C ON C.CategoryId = B.CategoryId 
    WHERE 
      PER.MobileNumber IS NOT NULL 
      AND PER.MobileNumber <> '' 

     AND (
       (
        (
        DATEDIFF(DAY, @CurrentDateTime, B.StartTime) = SMS.Duration 
        AND SMS.DurationType = 1 
        ) 
       OR (
        DATEDIFF(DAY, @CurrentDateTime, B.StartTime) = SMS.Duration * 7 
        AND SMS.DurationType = 2 
        ) 
       OR (
        DATEDIFF(DAY, @CurrentDateTime, B.StartTime) = SMS.Duration * 30 
        AND SMS.DurationType = 3 
        ) 
       ) 
       AND BeforeAfter = 0 

     OR (
      (
       (
        DATEDIFF(DAY, B.StartTime, @CurrentDateTime) = SMS.Duration 
        AND SMS.DurationType = 1 
        ) 
       OR (
        DATEDIFF(DAY, @CurrentDateTime, B.StartTime) = SMS.Duration * 7 
        AND SMS.DurationType = 2 
        ) 
       OR (
        DATEDIFF(DAY, @CurrentDateTime, B.StartTime) = SMS.Duration * 30 
        AND SMS.DurationType = 3 
        ) 
       ) 
      AND BeforeAfter = 1 
      ) 
      ) 

慢速計劃

enter image description here

快速計劃當我評論說OR SMS.CategoryId IS NULL

enter image description here

+0

需要2分鐘時會返回多少條記錄?快速版本有多少?查詢計劃說什麼? – Blorgbeard

+0

僅返回213條記錄。更快的退貨只有37. – Developer

+0

請包括兩個查詢計劃。 – Reinard

回答

1

把SMS.CategoryId和B.CategoryId在WHERE條件,然後檢查空 - 它更具可讀性的方式。嘗試運行以下查詢,它將表迭代週期減少1 1

SELECT 
    SMS.Id AS ConfigId 
    ,B.BookingId AS BookingId 
    ,B.StartTime AS BookingStartTime 
    ,B.EndTime AS BookingEndTime 
    ,B.BookingDate AS BookingDate 
    ,B.Price AS Price 

FROM 
    Booking B 
    INNER JOIN SMSConfiguration SMS 
     ON SMS.TenantId = B.TenantId 
WHERE 
    B.CategoryId = ISNULL(SMS.CategoryId,B.CategoryId) 
1

OR幾乎總是很慢。通常,使用UNION all查詢的速度要快得多。然而,我並不清楚加盟條件應該是什麼。你的意思是:

INNER JOIN SMSConfiguration SMS ON (SMS.CategoryId = B.CategoryId 
     OR SMS.CategoryId IS NULL) 
     AND SMS.TenantId = B.TenantId 

或者

INNER JOIN SMSConfiguration SMS ON SMS.CategoryId = B.CategoryId 
     OR (SMS.CategoryId IS NULL 
     AND SMS.TenantId = B.TenantId) 

第一是無論你做了什麼,即使你的意思是,你應該使用()要清楚,當有人去維護這個。

+0

另一個答案對我來說在8秒左右的時候會有些不錯。 'INNER JOIN SMSConfiguration SMS ON SMS.TenantId = B.TenantId WHERE B.CategoryId = ISNULL(SMS.CategoryId,B.CategoryId)'只有我嘗試過但在JOIN – Developer