簡體   English   中英

SQL連接查詢性能問題

[英]SQL join query performance issue

我有兩個表:

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條記錄)...

更新:我發現“(@pPassword = u。[Password])”也消除了問題,如果沒有它,它的執行效果很好,這與索引編制有關嗎?

這是執行計划:

執行計划

我的索引:

  1. [用戶]。[用戶]:

[UserID](ASC)-主鍵

  1. [用戶]。[電子郵件地址]

[UserID](ASC),[EmailAddressID](ASC)-主鍵

[EmailAddress](ASC)-唯一鍵

對於此查詢:

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)

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

也許這不是一個很好的解決方案,因為我無法對此進行測試,而是嘗試按照以下步驟進行操作以查看會發生什么情況?

;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;

您的第一個查詢包含索引,而第二個則沒有。

假設:EmailAddress是唯一的,因此該索引明確包含該字段以及EmailAddressID和UserID(如果它們是聚集索引)。 - 要么 -

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

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

您可能需要一個包含EmailAddress的索引(因為這些是您要作為過濾依據的字段),並包括其余的列。 INCLUDE子句)。 這將使您的索引成為第二個查詢的覆蓋索引,因此索引掃描就足夠了,並且不需要查找。

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

查詢計划將有助於檢查哪個(對於您當前的數據)哪個更好。 核實。

我找到了一個答案,盡管我不是一個正確的答案,但似乎可以解決問題,性能很棒! 而不是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])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM