[解決済み] なぜLINQ JOINはWHEREでリンクするよりもずっと速いのですか?
質問
最近 VS 2010 にアップグレードし、LINQ to Dataset を使って遊んでいます。私はASP.NET WebApplicationのHttpCacheにある認証のための強い型付けされたデータセットを持っています。
そこで私は、ユーザーが何かをすることを許可されているかどうかを確認する最も速い方法は何であるかを知りたいと思いました。 ここで は私のデータモデルと他の情報です。
私は3つの方法をチェックしました。
- 直接 データベース
- LINQクエリで ここで を条件とする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 秒。
- 場所 99,5404964 秒
- 結合: 1,815435 秒。
LINQ初心者としては最も読みやすいと思われますが、なぜJoinバージョンはwhere-syntaxよりもずっと速いのでしょうか。それとも、私のクエリに何か見落としがあったのでしょうか?
以下は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の利点は以前の何倍も大きくなりました。
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.Iteration。
- 0,0713669秒。
- 12,7395299 秒
2.イテレーション
- 0,0492458秒。
- 12,3885925 秒
3.イテレーション
- 0,0501982秒。
- 13,3474216 秒
平均値です。
- 参加: 0,0569367 秒。
- どこで 12,8251813 秒
ジョインが225倍高速化
結論
リレーションを指定するためにWHEREを避け、可能な限りJOINを使用する(間違いなく
LINQからDataSet
と
Linq-To-Objects
を一般に)使用することができます。
どのように解決するのですか?
-
最初のアプローチ(DBでのSQLクエリ)は、DBが結合を実行する方法を知っているので、非常に効率的です。しかし、他のアプローチはメモリ内で直接動作するため(Linq to DataSet)、これを比較するのはあまり意味がありません。
-
複数のテーブルを持つクエリと
Where
条件を持つクエリは、実際には カルテジアン積 を実行します。 では は条件を満たす行をフィルタリングします。これはつまりWhere
の条件は、行の各組み合わせ(n1 * n2 * n3 * n4)に対して評価されます。 -
は
Join
演算子は最初のテーブルから行を取り出し、次に 2 番目のテーブルからキーが一致する行だけを取り出し、さらに 3 番目のテーブルからキーが一致する行だけを取り出し、といった具合になります。これは、それほど多くの処理を行う必要がないため、より効率的です。
関連
-
[解決済み] WCFのデバッグ時にサーバーに自動的に踏み込むことができない
-
[解決済み] B "の印刷が "#"の印刷より劇的に遅いのはなぜですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] <は<=より速いのか?
-
[解決済み] INNER JOIN ON vs WHERE句
-
[解決済み] LINQで.Firstと.FirstOrDefaultを使用するタイミングは?
-
[解決済み] なぜJavaでは2 * (i * i)の方が2 * i * iより速いのですか?
-
[解決済み] なぜ[]はlist()よりも速いのですか?
-
[解決済み] Visual Studioの「Any CPU」ターゲットはどういう意味ですか?
-
[解決済み] LINQとLambdaでJoin/Whereを実現する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] COMExceptionエラー80040154を修復する方法は?
-
[解決済み] EF Coreのadd-migrationのビルドに失敗しました。
-
[解決済み] スマートクライアント・ソフトウェアファクトリーの体験談
-
[解決済み] Microsoft.NETFrameworkとMicrosoft.NETFramework64の違いは何ですか?
-
[解決済み] .NET WebRequestを使用してsharepointにファイルをアップロードすると、409/Conflict HTTPエラーが発生する理由?
-
[解決済み] CryptographicException「キーセットが存在しない」、ただしWCF経由に限る
-
[解決済み] 文字列から数字を抽出する正規表現
-
[解決済み] .net の OOM 問題を解決する必要があります。
-
[解決済み] Microsoft.ACE.OLEDB.12.0' プロバイダがローカルマシンに登録されていません。
-
[解決済み] WCF - メッセージサイズのクォータを増加させる方法