2013-08-02 122 views
0

我有一个800万用户的示例数据库,其中管理帐户页面需要8秒才能呈现。它归结为调用Membership GetUser的方法GetUserId。提高SimpleMembership查询性能?

的的getUser SQL看起来是这样的:

SELECT [UserId] FROM [Users] WHERE (UPPER([UserName]) = @0) 

当我运行在查询分析器以下几个问题我得到下面的结果

SELECT [UserId] FROM [Users] WHERE [UserName] = 'CARL' 
-- This question takes 11 milliseconds on my dev machine 

SELECT [UserId] FROM [Users] WHERE UPPER([UserName]) = 'CARL' 
-- This question takes 3.5 seconds on my dev machine 

username列有以下指标:

CREATE NONCLUSTERED INDEX IX_Users_UserName ON dbo.Users (UserName) 

可以更改sql查询吗?查询性能可以通过其他方式得到改进吗?

+0

这种确切的行为已经成为我们等待时间和负载的45%。我们正在扩大用户,3x活跃用户现在= 3倍等待和资源咀嚼。响应已经从1秒变为3秒,因为用户数量增加,数据库中只有650,326个用户......我正在探索使用Identity来取代SimpleMembership asap –

+1

@Hunter很容易改变源代码并运行自定义构建。这就是我所做的。 –

+0

谢谢!我今晚在我自己身上发现了这个!他们是一切开源的,这也必须是!当我最后看时,这是在MS的所有这些新举措之前。但最终要触及最少量的代码。我在这里跑这颗宝石。而男人是夜晚,白天......我将把它添加为答案。 http://i1.blogs.msdn.com/b/webdev/archive/2015/02/11/improve-performance-by-optimizing-queries-for-asp-net-identity-and-other-membership-providers .aspx –

回答

0

可以更改sql查询吗?

不,SQL查询被烧入简单成员资格提供程序的代码中。结帐与反射器WebMatrix.WebData.SimpleMembershipProvider.GetUserId方法,它看起来像这样的代码:

internal static int GetUserId(IDatabase db, string userTableName, string userNameColumn, string userIdColumn, string userName) 
{ 
    object obj2 = db.QueryValue("SELECT " + userIdColumn + " FROM " + userTableName + " WHERE (UPPER(" + userNameColumn + ") = @0)", new object[] { userName.ToUpperInvariant() }); 
    if (<GetUserId>o__SiteContainer5.<>p__Site6 == null) 
    { 
     <GetUserId>o__SiteContainer5.<>p__Site6 = CallSite<Func<CallSite, object, bool>>.Create(Binder.UnaryOperation(CSharpBinderFlags.None, ExpressionType.IsTrue, typeof(SimpleMembershipProvider), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) })); 
    } 
    if (<GetUserId>o__SiteContainer5.<>p__Site7 == null) 
    { 
     <GetUserId>o__SiteContainer5.<>p__Site7 = CallSite<Func<CallSite, object, object, object>>.Create(Binder.BinaryOperation(CSharpBinderFlags.None, ExpressionType.NotEqual, typeof(SimpleMembershipProvider), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.Constant, null) })); 
    } 
    if (!<GetUserId>o__SiteContainer5.<>p__Site6.Target(<GetUserId>o__SiteContainer5.<>p__Site6, <GetUserId>o__SiteContainer5.<>p__Site7.Target(<GetUserId>o__SiteContainer5.<>p__Site7, obj2, null))) 
    { 
     return -1; 
    } 
    if (<GetUserId>o__SiteContainer5.<>p__Site8 == null) 
    { 
     <GetUserId>o__SiteContainer5.<>p__Site8 = CallSite<Func<CallSite, object, int>>.Create(Binder.Convert(CSharpBinderFlags.ConvertExplicit, typeof(int), typeof(SimpleMembershipProvider))); 
    } 
    return <GetUserId>o__SiteContainer5.<>p__Site8.Target(<GetUserId>o__SiteContainer5.<>p__Site8, obj2); 
} 

您必须编写自定义成员提供,如果你想改变这种行为。

+0

这是一个内部静态方法...这是不幸的。 –

+0

Yeap,* internal static *,我最喜欢的类访问修饰符组合,我无法访问源代码:-) –

+0

https://aspnetwebstack.codeplex。com/:) –

1

按照MS建议运行下面的SQL来提高你的表现:

TIL,同时试图解决同样的问题。对UPPER的调用不使用索引。

试试这个在短期内,如果你能负担得起的资源:

ALTER TABLE Users ADD NormalizedName AS UPPER(UserName); 

CREATE NONCLUSTERED INDEX [IX_NormalizedName] ON [Users] ([NormalizedName] ASC); 

这样做后,我得到了非常合理的绩效进行简单的会员(足以维持我,直到我的身份或下次更换最好的事情。)

http://i1.blogs.msdn.com/b/webdev/archive/2015/02/11/improve-performance-by-optimizing-queries-for-asp-net-identity-and-other-membership-providers.aspx

和修改长远来看自己的代码和替换编译版本。 Carl R指出这个项目现在也是开源的。所以现在你可以改写它的味道。 https://aspnetwebstack.codeplex.com/SourceControl/latest#src/WebMatrix.WebData/SimpleMembershipProvider.cs