我们已经开始使用从该的NuGet包Microsoft.AspNet.Providers.Core提供的最新System.Web.Providers。 我们开始将我们的现有用户,并发现表现放缓,然后死锁的发生。 这与少于30,000名用户(远低于1,000,000我们需要创建)。 当我们调用提供者,它是从每个服务器上的多个线程和有运行同一过程的多台服务器。 这是能够创造一切,我们尽可能快地所需的用户和模拟,我们希望看到,当它上线的负载。
用于生成死锁日志的SQL Server包含下面的EF生成的SQL:
SELECT
[Limit1].[UserId] AS [UserId]
, [Limit1].[ApplicationId] AS [ApplicationId]
, [Limit1].[UserName] AS [UserName]
, [Limit1].[IsAnonymous] AS [IsAnonymous]
, [Limit1].[LastActivityDate] AS [LastActivityDate]
FROM
(SELECT TOP (1)
[Extent1].[UserId] AS [UserId]
, [Extent1].[ApplicationId] AS [ApplicationId]
, [Extent1].[UserName] AS [UserName]
, [Extent1].[IsAnonymous] AS [IsAnonymous]
, [Extent1].[LastActivityDate] AS [LastActivityDate]
FROM
[dbo].[Users] AS [Extent1]
INNER JOIN [dbo].[Applications] AS [Extent2] ON [Extent1].[ApplicationId] = [Extent2].[ApplicationId]
WHERE
((LOWER([Extent2].[ApplicationName])) = (LOWER(@p__linq__0)))
AND ((LOWER([Extent1].[UserName])) = (LOWER(@p__linq__1)))
) AS [Limit1]
我们手动运行查询和执行计划说,这是执行表扫描,即使有一个标的指数。 这样做的原因是使用LOWER([Extent1].[UserName])
我们着眼于供应商代码,看看如果我们做错了什么,或者如果有办法要么拦截或更换数据库访问代码。 我们没有看到任何选项来做到这一点,但我们确实找到了源LOWER
问题, .ToLower()
被调用的列名和参数两者。
return (from u in ctx.Users
join a in ctx.Applications on u.ApplicationId equals a.ApplicationId into a
where (a.ApplicationName.ToLower() == applicationName.ToLower()) && (u.UserName.ToLower() == userName.ToLower())
select u).FirstOrDefault<User>();
有谁知道,我们改变了供应商的行为不使用.ToLower的方式(),所以允许使用索引?