0

アカウントの管理ページのレンダリングに 8 秒かかる、800 万人のユーザーを持つサンプル データベースがあります。これは、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 に答える