[英]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])”也消除了問題,如果沒有它,它的執行效果很好,這與索引編制有關嗎?
這是執行計划:
我的索引:
[UserID](ASC)-主鍵
[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.