【发布时间】:2021-03-04 10:51:12
【问题描述】:
我有一个接受字符串并将其与多个字段进行比较的存储过程。但是,其中一个字段包含在将其与搜索字符串进行比较之前需要删除的其他字符。
例如
Create Or Alter Proc FindPosts3
(
@criteria AS nvarchar(25)
)
AS
Begin
Select P.OwnerUserId,P.CreationDate,p.Score,p.CommentCount,p.Body1
From Posts1 p Inner Join
(
Select p.OwnerUserId,max(p.CreationDate) as CreationDate
From Posts1 p
Group by p.OwnerUserId
) Sub On P.OwnerUserId = Sub.OwnerUserId AND P.CreationDate = Sub.CreationDate
Where p.Score = @criteria OR p.CommentCount = @criteria Or udfstripHtmlTags(p.body1) = @criteria
End
示例字段值是:
OwernerUserID---CreationDate----Score----CommentCount----Body
1 Aug 20, 2010 18 6 <p>null<p>
2 Dec 15, 2008 7 3 <b>variable<b>
3 Mar 07, 2011 15 20 <i>Arrays<i>
搜索正文字段时,使用 udfStripHtmlTag 函数删除 <p>, <b> and <i> 标记。这会导致 where 子句中的 Body 字段不再是“SARG”或会减慢查询速度的搜索参数。
在此示例中,我使用名为“udfStripHtmlTag”的函数从正文字段中删除 HTML 标记,然后再将其与标准进行比较。正如预期的那样,这会导致发生索引扫描,而不是使用为 body 字段创建的索引进行索引查找。事实上,这也会导致 score 和 commentcount 字段的索引不再用于此版本的查询中。在我使用联合而不是“或”的另一个版本中,仍然使用分数和commentcount 字段的索引。但是,由于对 body 字段的索引扫描,查询仍然很慢。
从字段中删除字符是一项要求。有没有我可以使用的替代技术来代替 where 子句中的标量函数?
注意。这不是我原来的问题代码。相反,它是基于 StackOverflow 数据库的代码。我最初的问题代码基于许多敏感数据/字段,因此我更容易使用替代数据库。同样,StackOverflow 数据库中的 body 字段已更改为 nvarchar(30),因此我可以为其创建索引。最后,在没有标量函数的情况下,查询在不到一秒的时间内运行。
【问题讨论】:
-
表值函数往往性能更高,但样本数据和所需结果会有所帮助。
-
从字段中删除字符是必需的。这是问题的根源。如果您需要搜索它并且需要从中删除 html 进行搜索,则在插入或更新该列时执行一次。
-
这不是我原来的问题代码那么您可能收到的任何建议都可能完全不合时宜。
-
@SMor,尽管这不是我最初的问题,但我能够复制相同的性能问题。问题在于 where 子句中的函数。如果我能在这里解决它,它也解决了我原来的问题。此外,您在更新或插入时的建议是正确的。但是我无法修改原始数据库。我只是在编写查询来检索数据。
-
@JohnCappelletti 我添加了一个表格,我不知道这是否有帮助。但是,我回来的结果很好。只是该函数导致不使用索引,导致查询需要大约一分半钟才能完成。
标签: sql-server tsql optimization indexing user-defined-functions