2013-07-10 113 views
0

我有表緩慢的存儲過程的查詢

Book: 
Id | Name | ... 

UrlRecord: 
Id | EntityId | Entityname | Slug >> to store id-less url for many other tables like Category | Book | BookChapter... 

所以數據巨大

ENTITYID =>包含標識在其他表等BOOKID,類別ID,chapterId ...

Id EntityId Entityname  Slug 
1  2  Category  truyen-tranh 
2  2  BookChapter chapter-one 

....

SearchBookDetails存儲過程:

SELECT p.Source, 
    (SELECT Slug from UrlRecord url where EntityName = 'Category' and EntityId = (SELECT top(1) CategoryId from Book_Category_Mapping bc where bc.BookId = p.Id) 
    ) as CategorySeName 

FROM .... 

性能非常慢,如果我有上面的CategorySeName子句,最多22秒,因爲這是一個沉重的查詢。

但是,我不知道如何提高性能,並仍然像上面那樣返回CategorySeName值。

+2

您是否試圖獲得查詢計劃?你很可能需要一個索引(EntityId,EntityName) – Bas

+1

C#與這個問題有什麼關係? –

+0

表中的索引是否包含在'WHERE'子句中使用的'WHERE'子句中使用的所有列? –

回答

0

您使用EntityId指向N個其他表,如bookid,categoryid,chapterId。
你是表設計是錯誤的,實際上不可能設置一個外鍵。

這是錯誤的,因爲這種方式你不能執行外鍵。
更糟糕的是,這會導致查詢性能下降,因爲沒有創建自動創建的索引,就像創建外鍵時一樣。

查詢優化器將因此拿出一個非常醜陋的執行計劃,這解釋了爲什麼它很慢。

如果你必須有一個對象ID,您可以createa一個觀點,做:

,但我很懷疑OBJECT_ID,或ENTITYID正如你所說的,沒有任何用處的,以你的方式。

PS:

字符串比較,而不是使用一個id始終是一個糟糕的主意

where EntityName = 'Category' 

結合這兩個反模式是一個特別好的主意。

+0

FK不會在SQL Server中自動創建索引。 THey必須手動創建索引。 – HLGEM

+0

此表格Urlrecord只是一個數據實體,與其他表格無關。其實,我正在爲我的項目使用http://nopcommerce.codeplex.com/。 –

1

你的問題是相關的子查詢。這是一個非常糟糕的技術,它將你的選擇語句改變成一個基本上是遊標的東西,並且逐行地運行它。如果您有大量數據集,請勿使用它們。改用派生表或CTE或臨時表。

+0

感謝您的意見。我會盡快做出一些改變。 –