최근에 VS 2010으로 업그레이드했고 LINQ to Dataset을 가지고 놀았습니다. ASP.NET WebApplication의 HttpCache에있는 권한 부여를위한 강력한 형식의 데이터 집합이 있습니다.
그래서 저는 사용자가 무언가를 할 권한이 있는지 확인하는 가장 빠른 방법이 무엇인지 알고 싶었습니다. 누군가가 관심이 있다면 여기 내 데이터 모델과 다른 정보가 있습니다.
세 가지 방법을 확인했습니다.
- 직접 데이터베이스
- Where 조건이 “Join”인 LINQ 쿼리 -구문
- 조인을 사용한 LINQ 쿼리 -구문
다음은 각 함수에 대해 1000 번 호출 한 결과입니다.
1. 반복 :
- 4,2841519 초
- 115,7796925 초
- 2,024749 초
2. 반복 :
- 3,1954857 초
- 84,97047 초
- 1,5783397 초
3. 반복 :
- 2,7922143 초
- 97,8713267 초
- 1,8432163 초
평균:
- 데이터베이스 : 3,4239506333 초
- Where : 99,5404964 초
- 가입 : 1,815435 초
Join-version이 where-syntax보다 훨씬 빠른 이유는 LINQ 초보자로서 가장 읽기 쉬운 것처럼 보이지만 쓸모 없게 만듭니다. 아니면 내 질문에서 놓친 것이 있습니까?
다음은 LINQ 쿼리입니다. 데이터베이스를 건너 뜁니다.
어디에 :
Public Function hasAccessDS_Where(ByVal accessRule As String) As Boolean
Dim userID As Guid = DirectCast(Membership.GetUser.ProviderUserKey, Guid)
Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule, _
roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule, _
role In Authorization.dsAuth.aspnet_Roles, _
userRole In Authorization.dsAuth.aspnet_UsersInRoles _
Where accRule.idAccessRule = roleAccRule.fiAccessRule _
And roleAccRule.fiRole = role.RoleId _
And userRole.RoleId = role.RoleId _
And userRole.UserId = userID And accRule.RuleName.Contains(accessRule)
Select accRule.idAccessRule
Return query.Any
End Function
붙다:
Public Function hasAccessDS_Join(ByVal accessRule As String) As Boolean
Dim userID As Guid = DirectCast(Membership.GetUser.ProviderUserKey, Guid)
Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule _
Join roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule _
On accRule.idAccessRule Equals roleAccRule.fiAccessRule _
Join role In Authorization.dsAuth.aspnet_Roles _
On role.RoleId Equals roleAccRule.fiRole _
Join userRole In Authorization.dsAuth.aspnet_UsersInRoles _
On userRole.RoleId Equals role.RoleId _
Where userRole.UserId = userID And accRule.RuleName.Contains(accessRule)
Select accRule.idAccessRule
Return query.Any
End Function
미리 감사드립니다.
편집 : 더 의미있는 성능 값을 얻기 위해 두 쿼리를 약간 개선 한 후 JOIN의 이점은 이전보다 훨씬 더 큽니다.
가입 :
Public Overloads Shared Function hasAccessDS_Join(ByVal userID As Guid, ByVal idAccessRule As Int32) As Boolean
Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule _
Join roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule _
On accRule.idAccessRule Equals roleAccRule.fiAccessRule _
Join role In Authorization.dsAuth.aspnet_Roles _
On role.RoleId Equals roleAccRule.fiRole _
Join userRole In Authorization.dsAuth.aspnet_UsersInRoles _
On userRole.RoleId Equals role.RoleId _
Where accRule.idAccessRule = idAccessRule And userRole.UserId = userID
Select role.RoleId
Return query.Any
End Function
어디에 :
Public Overloads Shared Function hasAccessDS_Where(ByVal userID As Guid, ByVal idAccessRule As Int32) As Boolean
Dim query = From accRule In Authorization.dsAuth.aspnet_AccessRule, _
roleAccRule In Authorization.dsAuth.aspnet_RoleAccessRule, _
role In Authorization.dsAuth.aspnet_Roles, _
userRole In Authorization.dsAuth.aspnet_UsersInRoles _
Where accRule.idAccessRule = roleAccRule.fiAccessRule _
And roleAccRule.fiRole = role.RoleId _
And userRole.RoleId = role.RoleId _
And accRule.idAccessRule = idAccessRule And userRole.UserId = userID
Select role.RoleId
Return query.Any
End Function
1000 번의 통화 결과 (빠른 컴퓨터에서)
- 가입 | 2. 어디서
1. 반복 :
- 0,0713669 초
- 12,7395299 초
2. 반복 :
- 0,0492458 초
- 12,3885925 초
3. 반복 :
- 0,0501982 초
- 13,3474216 초
평균:
- 가입 : 0,0569367 초
- Where : 12,8251813 초
가입 속도가 225 배 빠릅니다.
결론 : 관계를 지정하기 위해 WHERE를 피하고 가능할 때마다 JOIN을 사용하십시오 (확실히 LINQ to DataSet 및 Linq-To-Objects
일반적으로).
답변
-
첫 번째 방법 (DB의 SQL 쿼리)은 DB가 조인을 수행하는 방법을 알고 있기 때문에 매우 효율적입니다. 그러나 메모리에서 직접 작동하기 때문에 다른 접근 방식과 비교하는 것은 실제로 의미가 없습니다 (Linq에서 DataSet로).
-
여러 테이블과
Where
조건 이있는 쿼리는 실제로 모든 테이블 의 데카르트 곱을 수행 한 다음 조건을 충족하는 행 을 필터링합니다. 즉,Where
각 행 조합 (n1 * n2 * n3 * n4)에 대해 조건이 평가됩니다. -
Join
운영자는 제 테이블에서 매칭 키 행만 등 번째 테이블에서 매칭 키 만 행을 얻어 다음, 제 테이블의 행 걸린다. 많은 작업을 수행 할 필요가 없기 때문에 훨씬 더 효율적입니다.
답변
이 Join
방법은 테이블을 결합하여 결과를 관련 조합으로 줄이는 방법을 알고 있기 때문에 훨씬 빠릅니다. 당신이 사용하는 경우 Where
의 관계를 지정하기 위해서는 가능한 모든 조합을 만든 다음 관련있는 조합을 볼 수있는 조건을 테스트 할 수 있습니다.
이 Join
메서드는 두 테이블을 빠르게 압축하는 인덱스로 사용할 해시 테이블을 설정할 수 있으며, Where
모든 조합이 이미 생성 된 후에 메서드가 실행되므로 사전에 조합을 줄이는 트릭을 사용할 수 없습니다.
답변
당신이 정말로 알아야 할 것은 두 문장을 위해 만들어진 SQL이다. 몇 가지 방법이 있지만 가장 간단한 방법은 LinqPad를 사용하는 것입니다. 쿼리 결과 바로 위에 SQL로 변경되는 몇 가지 버튼이 있습니다. 그것은 당신에게 다른 무엇보다 더 많은 정보를 줄 것입니다.
그래도 훌륭한 정보를 공유했습니다.