Почему LINQ JOIN намного быстрее, чем связывание с WHERE?

Я недавно обновился до VS 2010 и экспериментирую с LINQ to Dataset. У меня есть строго типизированный набор данных для авторизации, который находится в HttpCache веб-приложения ASP.NET.

Поэтому я хотел знать, какой на самом деле самый быстрый способ проверить, имеет ли пользователь право что-либо делать. Здесь моя модель данных и другая информация, если кому-то интересно.

Я проверил 3 способа:

  1. прямой база данных
  2. LINQ-запрос с условиями Где как «Соединение» - Синтаксис
  3. Запрос LINQ с Соединение - Синтаксис

Это результаты с 1000 вызовов для каждой функции:

1. Итерация:

  1. 4,2841519 сек.
  2. 115,7796925 сек.
  3. 2, 024749 сек.

2. Итерация:

  1. 3,1954857 сек.
  2. 84,97047 сек.
  3. 1,5783397 сек.

3. Итерация:

  1. 2,7922143 сек.
  2. 97 871 3267 сек
  3. 1,84 32 163 сек

Среднее значение:

  1. База данных: 3,4239506333 сек
  2. Где: 99 5404964 сек
  3. Присоединение: 1815435 сек.

Почему версия Join намного быстрее, чем синтаксис where, что делает ее бесполезной, хотя для новичка в 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 во много раз больше, чем раньше:

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 вызовов (на более быстром компьютере)

  1. Присоединиться | 2. Где

1. Итерация:

  1. 0,0713669 сек.
  2. 12,7395299 сек.

2. Итерация:

  1. 0,0492458 сек.
  2. 12,3885925 сек.

3. Итерация:

  1. 0,0501982 сек.
  2. 13,3474216 сек.

Среднее:

  1. Соединение: 0,0569367 сек.
  2. Где: 12,8251813 сек.

Объединение в 225 раз быстрее

Заключение: избегайте WHERE для указания отношений и используйте JOIN, когда это возможно (определенно в LINQ to DataSet и Linq-To-Objects в целом) .

96
задан Community 23 May 2017 в 11:46
поделиться