我遇到了一點性能問題。我得到了以下數據庫模型。 選擇導航屬性爲空的條目的最佳方法
我希望選擇實體1中沒有外鍵的所有條目,換句話說,導航屬性必須爲空。
我已經拿出以下的LINQ查詢context.Entity2Set.Where(x => x.Entity1 == null);
,它的工作原理,但它很慢。所以我想知道是否有更好(更快)的方式(其他索引)來選擇條目。
最後,我想從Entity4中選擇條目,因此性能是一個問題。
我遇到了一點性能問題。我得到了以下數據庫模型。 選擇導航屬性爲空的條目的最佳方法
我希望選擇實體1中沒有外鍵的所有條目,換句話說,導航屬性必須爲空。
我已經拿出以下的LINQ查詢context.Entity2Set.Where(x => x.Entity1 == null);
,它的工作原理,但它很慢。所以我想知道是否有更好(更快)的方式(其他索引)來選擇條目。
最後,我想從Entity4中選擇條目,因此性能是一個問題。
您正在查詢關係中的委託人(Entity2
),而不是受撫養人(Entity1
)。這意味着外鍵在表Entity1
中,生成的SQL查詢不僅僅是表Entity2
中列值的查詢。爲了得到期望的結果,SQL查詢必須加入(通過LEFT OUTER JOIN
)這兩個表。
如果它是一對多關係,則您的查詢如下所示:「獲取所有沒有訂單項的訂單」。這不能通過單獨檢查Order
表來實現,因爲外鍵在表OrderItem
中,並且查詢必須加入這兩個表。事實上,在這個例子中,可以通過索引表OrderItem
中的外鍵列來改進查詢的性能。
不幸的是,在您的示例中,您無法通過對列進行索引來改進查詢,因爲您有一對一的關係(而非一對多關係)。由於EF的一對一關係始終是共享的主鍵關聯,因此表Entity1
中的外鍵同時是其主鍵Id
。
這意味着您的外鍵列已被索引 - 即表Entity1
中的聚集主鍵索引。
生成的SQL查詢,像這樣:
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[OtherColumn] AS [OtherColumn]
FROM [dbo].[Entity2] AS [Extent1]
LEFT OUTER JOIN [dbo].[Entity1] AS [Extent2] ON [Extent1].[Id] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Entity1] AS [Extent3] ON [Extent2].[Id] = [Extent3].[Id]
WHERE [Extent3].[Id] IS NULL
正如你可以看到表由索引Id
列加入。第二個和多餘的LEFT OUTER JOIN
是實體框架的SQL生成中的一個缺陷,對EF < 5.0有效。我不確定它是否在EF> = 5.0中解決。我不知道對於查詢性能是否真的很重要,因爲行通過同一列連接到表本身,所以我希望SQL查詢優化器能夠識別它並忽略執行計劃中的行。
實質上:您的LINQ查詢很好,即使不向列中添加任何其他索引,也無法提高性能。
不過,我的建議是找出是很慢。它確實是SQL查詢,還是從LINQ查詢轉換爲SQL,還是可能是返回結果集的對象實現等?我要做的第一步是將生成的SQL查詢粘貼到SQL Server Management Studio中,並查看性能如何。即使你不改變LINQ查詢,也可能有其他機會來提高性能。
這是相當豐富的,謝謝。 – 2013-02-17 17:00:28
你說
沒有索引
但對於這個問題,那將是一個錯誤。索引幾乎可以即時找到所有空引用。
沒有'NULL'引用,因爲FK在'Entity1'中,而不在'Entity2'中。 – Slauma 2013-02-17 16:25:49
問題說導航屬性必須爲空。所以必須有空值。 – qujck 2013-02-17 16:55:22
在LINQ查詢中使用的導航屬性不是代表外鍵側的導航屬性,它是反轉屬性。 (您可以從圖中的'0..1'到'1'結束,即'Entity2'是主體。)如果*不存在則爲'null' *表'Entity1'中的記錄它指的是表'Entity2',而不是FK爲NULL時。 (在這種情況下,因爲它是FK是PK的一對一關係,所以它永遠不會是'NULL')。 – Slauma 2013-02-17 17:19:17
在調試模式下懸停在linq查詢上將允許您查看將要生成和執行的實際SQL。看看這可能會讓你對Linq查詢實際執行的內容有所瞭解,從而幫助解決性能問題。 – Chris 2013-02-16 15:22:47
這應該是一個快速查詢。聽起來就像你需要外鍵列上的索引。 – 2013-02-16 15:27:00
爲什麼你不想索引? – 2013-02-16 17:43:04