0

我有一个包含 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查询可以改吗?可以通过其他方式提高查询性能吗?

4

2 回答 2

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

于 2015-08-31T08:43:39.953 回答
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);
}

如果要更改此行为,则必须编写自定义成员资格提供程序。

于 2013-08-02T13:03:41.107 回答