慢存储的proc查询

时间:2013-07-10 12:13:55

标签: sql-server

我有桌子

Book: 
Id | Name |  ...

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

所以数据巨大

ENTITYID =>包含其他表中的ID,如bookid,categoryid,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 个答案:

答案 0 :(得分:1)

您的问题是相关的子查询。这是一种非常糟糕的技术,可以将您的选择状态更改为基本上是游标的行,然后逐行地运行它。如果您有大量数据集,请不要使用它们。请改用派生表或CTE或临时表。

答案 1 :(得分:0)

您使用EntityId指向其他N个表,例如bookid,categoryid,chapterId 你的桌面设计是错误的,实际上不可能设置外键。

这是错误的,因为这样你就无法强制执行外键 更糟糕的是,这会导致查询性能变慢,因为没有像创建外键时那样自动创建索引。

因此,查询优化器会提出一个非常丑陋的执行计划,这解释了为什么这么慢。

如果您必须拥有对象ID,则可以创建视图并执行:

COALESCE(bookid, categoryid, chapterId) AS EntityId 

但我非常怀疑object_id,或者你称之为EntityId,对你有任何用处。

<强> PS:

字符串比较而不是使用id总是一个坏主意

where EntityName = 'Category'
将这两种反模式结合起来是一个特别好的主意。