我有桌子
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值。
答案 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'
将这两种反模式结合起来是一个特别好的主意。