私は最近VS 2010にアップグレードし、LINQ to Datasetで遊んでいます。ASP.NET WebApplicationのHttpCacheにある承認用の厳密に型指定されたデータセットがあります。
だから私は、ユーザーが何かをすることを許可されているかどうかを確認する最も速い方法が実際に何であるか知りたいと思った。ここに私のデータモデルと、誰かが興味を持っている場合のその他の情報があります。
私は3つの方法をチェックしました:
- 直接データベース
- Where条件が "Join"のLINQクエリ-構文
- 結合を使用したLINQクエリ-構文
これらは、各関数を1000回呼び出した結果です。
1.反復:
- 4,2841519秒。
- 115,7796925秒。
- 2,024749秒
2.Iteration:
- 3,1954857秒
- 84,97047秒
- 1,5783397秒
3.反復:
- 2,7922143秒
- 97,8713267秒。
- 1,8432163秒
平均:
- データベース:3,4239506333秒。
- 場所:99,5404964秒。
- 参加:1,815435秒
なぜLINQの初心者が最も読みやすいように見えますが、Joinバージョンはwhere構文よりもはるかに高速であり、役に立たなくなります。または、クエリで何かを見逃しましたか?
これが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.Iteration:
- 0,0492458秒。
- 12,3885925秒
3.反復:
- 0,0501982秒
- 13,3474216秒
平均:
- 参加:0,0569367秒
- ここで:12,8251813秒。
参加は225倍速くなります
結論: WHEREを使用してリレーションを指定し、可能な場合は常にJOINを使用します(LINQ to DataSetおよびLinq-To-Objects
一般的には間違いなく)。
Join
なぜ使用しても害はありません。最初から最適化されたコードを記述できるのであれば、なぜオプティマイザに依存するのでしょうか。また、意図が明確になります。したがって、SQLでJOINを選択する必要があるのと同じ理由です。