2017-07-28 120 views
1

我有兩個表:SQL連接查詢性能問題

1. [User].[Users] 

    -------------------------------------------------- 
    |[UserID]   | INT   (primary key) | 
    |[Username]  | NVARCHAR(50)    | 
    |[IsVerified]  | BIT       | 
    |[ModifiedDate] | DATETIME     | 
    -------------------------------------------------- 

2. [User].[EmailAddresses] 
    -------------------------------------------------- 
    |[UserID]   | INT   (foreign key) | 
    |[EmailAddressID] | INT       | 
    |[EmailAddress] | NVARCHAR(50)    | 
    |[IsPrimary]  | BIT       | 
    |[IsVerified]  | BIT       | 
    |[ModifiedDate] | DATETIME     | 
    -------------------------------------------------- 

現在,當我運行此查詢,它執行很大:

SELECT 
    u.[UserID], 
    u.[Username], 
    u.[IsVerified], 
    e.[EmailAddressID], 
    e.[EmailAddress] 
FROM [User].[Users] u 
INNER JOIN [User].[EmailAddresses] e 
    ON e.[UserID] = u.[UserID] 
WHERE (@pEmailAddress = e.[EmailAddress]) 
AND (@pPassword = u.[Password]) 

,當我運行此查詢,它表現可怕:

SELECT 
    u.[UserID], 
    u.[Username], 
    u.[IsVerified], 
    e.[EmailAddressID], 
    e.[EmailAddress], 
    e.[IsPrimary], 
    e.[IsVerified], 
    e.[ModifiedDate] 
FROM [User].[Users] u 
INNER JOIN [User].[EmailAddresses] e 
    ON e.[UserID] = u.[UserID] 
WHERE (@pEmailAddress = e.[EmailAddress]) 
AND (@pPassword = u.[Password]) 

請注意,我只是從這3列中加1(e.[IsPrimary]e.[IsVerified],e.[ModifiedDate]),並且它演變成可怕(延遲5-6秒)...

它可能是什麼?我沒有加入表格嗎?是因爲我在兩個表中都有一些同名的列?

另外,我沒有太多的記錄...(約20條)...

UPDATE: 我發現 「(。@pPassword = U [密碼])」 還刪除這個問題,沒有它就表現出色,它與索引有什麼關係?

這裏是執行計劃:

Execution plan

我的索引:

  1. [用戶] [用戶]:

[用戶名](ASC) - 主鍵

  • [用戶] [EmailAddresses]
  • [用戶名](ASC),[EmailAddressID](ASC) - 主鍵

    [EmailAddress的] (ASC) - 唯一鍵

    +0

    你檢查過查詢計劃?在SQL Server Management Studio中,查詢上方有一個按鈕,可在執行後運行估計的計劃。這將爲您提供查詢的可視化步驟,並按百分比向您顯示查詢中最昂貴的部分。它也會建議你應該創建的任何索引。請運行它,讓我們知道它回來了。 – Dom

    +0

    @DomDaFonte謝謝,我添加了一個執行計劃... –

    +0

    沒問題。在您的查詢計劃中,我看到電話字段上有一個聚集索引掃描,儘管我看不到其中的電話號碼。 1.爲每個表運行sp_spaceused併發送結果。 2.你可以右鍵單擊Ssms中的表,創建一個類似的併爲每個表發佈ddl? 3.最後是密碼字段散列?我可能會在ddl中看到這個,但讓我知道。 – Dom

    回答

    0

    我找到了答案,雖然我不是,如果它是正確的,但似乎解決了這個問題,性能是偉大的!而不是5秒執行,它得到0.365,這太棒了!

    我沒發現什麼毛病我的索引,或者在3列,我添加的1 ...

    基本上,我改變了查詢 - 我打開兩個表中查詢,所以如果我有:

    SELECT 
        u.[UserID], 
        u.[Username], 
        u.[IsVerified], 
        e.[EmailAddressID], 
        e.[EmailAddress], 
        e.[IsPrimary], 
        e.[IsVerified], 
        e.[ModifiedDate] 
    FROM [User].[Users] u 
    INNER JOIN [User].[EmailAddresses] e ON e.[UserID] = u.[UserID] 
    WHERE (@pEmailAddress = e.[EmailAddress]) AND (@pPassword = u.[Password]) 
    

    現在,它是:

    SELECT 
        u.[UserID], 
        u.[Username], 
        u.[IsVerified], 
        e.[EmailAddressID], 
        e.[EmailAddress], 
        e.[IsPrimary], 
        e.[IsVerified], 
        e.[ModifiedDate] 
    FROM [User].[EmailAddresses] e 
    INNER JOIN [User].[Users] u ON u.[UserID] = e.[UserID] 
    WHERE (e.[EmailAddress] = @pEmailAddress) AND (@pPassword = u.[Password]) 
    
    0

    對於此查詢:

    SELECT u.[UserID], u.[Username], u.[IsVerified], e.[EmailAddressID], 
         e.[EmailAddress], e.[IsPrimary], e.[IsVerified], e.[ModifiedDate] 
    FROM [User].[Users] u INNER JOIN 
        [User].[EmailAddresses] e 
         ON e.[UserID] = u.[UserID] 
    WHERE (@pEmailAddress = e.[EmailAddress]) AND (@pPassword = u.[Password]); 
    

    您想嘗試下列索引:users(password, userid)email(emailaddress, userid)

    +0

    但是如果沒有3列(例如[IsPrimary],例如[IsVerified],[[ModifiedDate])它表現很好,我認爲它與索引無關,這些列不應該影響性能,但不知何故做... –

    0

    嘗試運行解釋或執行計劃以查看它是如何執行的。解釋計劃將告訴您是否正在使用索引或表掃描。我猜測第一個查詢能夠使用索引作爲覆蓋索引來檢索emailAddressID和emailAddress,但第二個查詢需要讀取實際表,因爲它不返回索引中的列。如果您沒有將emailAddressID和emailAddress編入索引,請嘗試將它們添加爲索引。

    0

    也許不是一個好的解決方案,因爲我無法測試,但嘗試下面看看會發生什麼?

    ;WITH CTE AS(
    SELECT e.* 
    FROM [User].[Users] u 
    INNER JOIN [User].[EmailAddresses] e ON e.[UserID] = u.[UserID] 
    WHERE (@pEmailAddress = e.[EmailAddress]) AND (@pPassword = u.[Password]) 
    ) 
    SELECT [IsPrimary], [IsVerified], [ModifiedDate] 
    FROM CTE; 
    
    +0

    謝謝,我試過了,仍然拖延性能... –

    0

    你的第一個查詢被索引覆蓋,你的第二個查詢不是。

    假設:EmailAddress是唯一的,因此該索引顯式包含該字段加上EmailAddressID和UserID(如果它們是聚簇索引)。 - 或 -

    EmailAddressID和UserID是PK,並且EmailAddress至少有一個索引。

    當您添加一個附加字段時,這將導致至少一次seek + key查找從表中檢索數據。

    您可能需要包含EmailAddress的索引(因爲這些是您要過濾的字段)幷包含其餘列。 (INCLUDE子句)。這會使您的索引成爲第二個查詢的覆蓋索引,因此索引掃描就足夠了,無需查找。

    (可選)您可以使用UserID嘗試類似的覆蓋索引。

    查詢計劃將有助於檢查哪一個更好(針對當前數據)。覈實。