[英]SQL join query performance issue
I have two tables: 我有两个表:
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 |
--------------------------------------------------
Now, when I run this query, it performs great: 现在,当我运行此查询时,它执行得很好:
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])
But , when I run this query, it performs horribly: 但是 ,当我运行此查询时,它的表现非常糟糕:
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])
Note that I just add 1 from these 3 columns ( e.[IsPrimary]
, e.[IsVerified]
, e.[ModifiedDate]
), and it turns to perform horribly (5-6 seconds delay)... 请注意,我只是从这3列中添加1( e.[IsPrimary]
, e.[IsVerified]
, e.[ModifiedDate]
),它的执行效果惊人(延迟5-6秒)...
What could it be? 会是什么呢? am I not joining the tables right? 我不参加餐桌吗? is it because I have some columns with the same name in both tables? 是因为两个表中都有一些具有相同名称的列吗?
Also, I don't have many records... (about 20 records)... 而且,我没有很多记录...(约20条记录)...
UPDATE: I found that "(@pPassword = u.[Password])" also removes the problem, it performs great without it, does it have something to do with indexing? 更新:我发现“(@pPassword = u。[Password])”也消除了问题,如果没有它,它的执行效果很好,这与索引编制有关吗?
Here is the execution plan: 这是执行计划:
My indexes: 我的索引:
[UserID] (ASC) - Primary key [UserID](ASC)-主键
[UserID] (ASC), [EmailAddressID] (ASC) - Primary key [UserID](ASC),[EmailAddressID](ASC)-主键
[EmailAddress] (ASC) - Unique key [EmailAddress](ASC)-唯一键
For this query: 对于此查询:
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]);
You want to try the following indexes: users(password, userid)
and email(emailaddress, userid)
. 您想尝试以下索引: users(password, userid)
和email(emailaddress, userid)
。
Try running an explain or execution plan to see how it's executed. 尝试运行解释或执行计划以查看其执行方式。 The explain plan will tell you whether indexes or table scans are being used. 说明计划将告诉您是否正在使用索引或表扫描。 I am guessing the first query is able to use an index as a covered index to retrieve emailAddressID and emailAddress but the second query is required to read the actual table since it's returning columns not in the index. 我猜第一个查询能够使用索引作为覆盖索引来检索emailAddressID和emailAddress,但是第二个查询需要读取实际表,因为它返回不在索引中的列。 If you don't have emailAddressID and emailAddress indexed, try adding them as an index. 如果您没有为emailAddressID和emailAddress编制索引,请尝试将它们添加为索引。
Perhaps not a good solution as I can't test that but try following to see what will happen? 也许这不是一个很好的解决方案,因为我无法对此进行测试,而是尝试按照以下步骤进行操作以查看会发生什么情况?
;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;
Your first query is covered by indexes, your second is not. 您的第一个查询包含索引,而第二个则没有。
Assumptions: EmailAddress is unique, thus that index explicitly contains that field plus EmailAddressID and UserID if they are the clustered index. 假设:EmailAddress是唯一的,因此该索引明确包含该字段以及EmailAddressID和UserID(如果它们是聚集索引)。 --OR-- - 要么 -
EmailAddressID and UserID are the PK and there is at least an index on EmailAddress. EmailAddressID和UserID是PK,并且EmailAddress上至少有一个索引。
When you add an additional field, that will lead to at least a seek+key lookup to retrieve the data from the table. 当您添加其他字段时,将至少导致一次seek + key查找,以从表中检索数据。
You may want an index containing the EmailAddress (since these are the field you are filtering by) and include the rest of the columns. 您可能需要一个包含EmailAddress的索引(因为这些是您要作为过滤依据的字段),并包括其余的列。 ( INCLUDE
clause). ( INCLUDE
子句)。 This would render your index a covering index for your second query, therefore an index scan would be enough and no need for lookup. 这将使您的索引成为第二个查询的覆盖索引,因此索引扫描就足够了,并且不需要查找。
Optionally you can try a similar covering index using UserID. (可选)您可以尝试使用UserID进行类似的覆盖索引。
A query plan will help a lot to check which one is better (for your current data). 查询计划将有助于检查哪个(对于您当前的数据)哪个更好。 Check it. 核实。
I found an answer, though I don't if it's the right one, but seems to solve the issue, performance is great! 我找到了一个答案,尽管我不是一个正确的答案,但似乎可以解决问题,性能很棒! instead of 5 seconds execution, it gets 0.365, this is great! 而不是5秒的执行时间,它得到0.365,这太好了!
I didn't find anything wrong with my indexes, or in 1 of the 3 columns I added... 我的索引没有发现任何问题,也没有发现我添加的3列中的1列...
Basically, I changed the query - I turned both tables in the query, so if I had: 基本上,我更改了查询-在查询中同时打开了两个表,因此如果有:
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])
Now, it is: 现在它是:
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.