2016-11-20 82 views
0

我得到了這個查詢,在生產環境中非常慢。我想知道爲什麼以及是否有更好的方法來達到同樣的結果。爲什麼我的linq到SQL查詢很慢?

public async Task<Membership> FindByEmailByAccessL1OrL3OrL4Async(string email) 
{ 
    return await (from m in this.Queryable() 
        where m.Email == email 
         && (m.RoleMemberships.Select(r => r.RoleId).Contains(RoleConstants.ACCESSGRANTEDL1ID) 
          || m.RoleMemberships.Select(r => r.RoleId).Contains(RoleConstants.ACCESSGRANTEDL3ID) 
          || m.RoleMemberships.Select(r => r.RoleId).Contains(RoleConstants.ACCESSGRANTEDL4ID)) 
        select m).SingleOrDefaultAsync(); 
} 

簡而言之,此查詢的目的是通過電子郵件獲取用戶成員資格並繼續登錄。我有更多的用戶會員資格,這個查詢會更慢。

謝謝

大衛

編輯

this.Queryable()是做select * from Memberships的等價物。 Membership表有許多角色,並且角色有許多成員。

此外,成員資格表最多需要12秒才能獲取240行的登錄信息。我必須按角色過濾,因爲系統中的電子郵件值不是唯一的。只有一些角色才能訪問登錄,並且這些角色將擁有唯一的電子郵件。這就是爲什麼我必須過濾。此查詢返回一個成員資格以繼續進行登錄,該查詢通過上面的查詢進行選擇。所以沒有IQueryableIEnumerableList,只是SingleOrDefault值。

+0

'this.Queryable()'???你不提供太多的信息.​​.什麼是「這個」? Queryable()方法返回什麼?顯示該代碼? – user3185569

+0

對不起!代碼位於存儲庫架構內。我在編輯部分提供了更多信息。 –

+0

我們可能需要查看SQL表定義以及任何索引。 – RBarryYoung

回答

3

我想生成的查詢是非常糟糕的,因爲你做同樣的事情多次是:

m.RoleMemberships.Select(r => r.RoleId) 

相反,你可以使用一次做到這一點:

public Task<Membership> FindByEmailByAccessL1OrL3OrL4Async(string email) 
{ 
    return (from m in this.Queryable() 
      where m.Email == email 
       && (m.RoleMemberships.Any(
        r => r.RoleId == RoleConstants.ACCESSGRANTEDL1ID 
         || r.RoleID == RoleConstants.ACCESSGRANTEDL3ID 
         || r.RoleID == RoleConstants.ACCESSGRANTEDL4ID) 
      select m).SingleOrDefaultAsync(); 
} 

的上面會讓事情變得更好,我猜。您可以使用調試器在兩種情況下檢查生成的查詢。

另外請注意,您不需要等待結果,只需返回任務,調用者需要等待它。

+0

「是非常樂隊」 - 你的意思是「壞」,「寬」還是其他? –

+0

@MarkSchultheiss錯字修正。感謝您指出了這一點。 – user3185569

0

我認爲有很多數據需要加載,EF是非常緩慢的映射技術,它會創建有趣的查詢(你可以看到這個here)。你是否有性能問題?也許你應該選擇其他映射技術(stacks dapper例如Dapper)。當我們進行測試時,速度比EF快兩倍。

+0

你如何推斷​​EF在這裏玩? –

+0

再一次,如果我們有大量的數據,它不是很快,這就是爲什麼我認爲這是這種情況 –