我有一个包含800万用户的示例数据库,其中管理帐户页面需要8秒才能呈现。它归结为调用Membership GetUser的GetUserId方法。
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 :(得分:1)
根据MS推荐,运行以下SQL以提高性能:
在尝试解决同样问题的同时TIL。对UPPER的调用不使用索引。如果您能负担得起资源,请在短期内尝试:
ServiceContract
在这样做之后,我从简单的会员资格中得到了非常合理的表现(足以支持我,直到我用身份或下一个最好的东西取而代之。)
从长远来看自己修改代码并替换已编译的版本。 Carl R指出这个项目现在也是开源的。所以现在你可以重新品尝它。 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
答案 1 :(得分: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);
}
如果要更改此行为,则必须编写自定义成员资格提供程序。