1

인증을 위해 SimpleMembershipProvider를 사용하는 .NET MVC4/Webapi2 앱을 만들었습니다. yersterday 이후, 모든 앱이 매우 느려서 NewRelic으로 모니터링했습니다. 데이터베이스는 웹 요청의 95 %를 사용하고, 다음과 같은 SQL 요청은 데이터베이스의 시간 소비의 99 %를 차지한다 :사용자가 SimpleMembershipProvider를 사용하는 .NET MVC에서 매우 느립니다.

WebSecurity.CurrentUserId 

550이 :이은에 의해 호출 가정

SELECT [Id] FROM [User] WHERE (UPPER([UserGuid]) = UPPER(@?)) 

사용자 테이블에서 000 행.

이 요청을 너무 늦추는 이유를 알고 있습니까?

답변

4

문제는 모든 쿼리에 대해 550,000 개의 레코드를 검색한다는 것입니다. 물론 이것은 매우 느릴 것입니다. 첫 번째 단계는 UserGuid 필드에 대한 색인을 정의하는 것입니다.

CREATE INDEX 
    UX_User_UserGuid 
ON [User] (
    [UserGuid] 
); 

정의 할 때 도움이되는지 확인하십시오. 99 %는 모든 레코드에 대해 UPPER 호출을 계산해야하기 때문에 그렇지 않습니다. 따라서 두 번째 단계는 UserGuid가 대소 문자를 구분하지 않기 때문에 UPPER 호출이 필요하지 않음을 확인하는 것입니다.

SELECT 
    collation_name 
FROM 
    sys.columns 
WHERE 
    object_id = OBJECT_ID('User') 
    AND name = 'UserGuid' 

당신의 결과는 "대소 문자 구분"을 의미한다 "CI"을 포함한다. 아니요 인 경우 데이터 정렬을 변경해야합니다.

세 번째 문제는 SimpleMembershipProvider 내부입니다. UPPER 호출은 하드 코드되어 있으므로 구현과 직접 교체해야합니다. Smth는 다음을 좋아했습니다 :

public class MyCustomProvider : WebMatrix.WebData.SimpleMembershipProvider 
{ 
    public override MembershipUser GetUser(string username, bool userIsOnline) 
    { 
     int userId = /* 
      get from your database without any UPPER calls 
      just like "SELECT [Id] FROM [User] WHERE [UserGuid] = @?" 
     */ 

     return this.GetUser(userId, userIsOnline); 
    } 
} 
+0

고마워요. – Raph

+0

this.GetUser (userId, userIsOnline)가 NotSupportedException을 던졌습니다. 이유가 있습니까? – Raph

+1

인스턴스를 직접 "새로운 MembershipUser (Membership.Provider.Name, username, userId, null, null, null, true, false, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime. MinValue); ". 많은 기본값을 설정했지만 userId와 동일한 쿼리에서 선택된 멤버 정보로 채울 수 있습니다. – Stan

관련 문제