2013-08-02 3 views
0

У меня есть образец базы данных с 8 миллионами пользователей, где страница управления аккаунтом занимает 8 секунд для рендеринга. Это сводится к методу GetUserId, вызывающему членство GetUser.Улучшение производительности запросов SimpleMembership?

SQL-GetUser выглядит следующим образом:

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 активных пользователей в настоящее время = 3x ожидания и ресурсы жевали. ответ прошел от 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, чтобы улучшить производительность:

сезам, пытаясь решить эту же проблему. Вызов 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

Смежные вопросы