参数化 SQL 和 NULL 运行缓慢

发布于 2024-10-26 22:58:55 字数 524 浏览 1 评论 0原文

我正在从.net 调用一些参数化sql。我不知道为什么,但是与不包含参数时相比,在检查参数是否为 NULL 时,sql 运行速度相当慢:

所以这个:

exec sp_executesql N'
 SELECT [id]
 FROM [tblAddress] (nolock)
 WHERE 1 = 1
 AND ([id] = @id OR @id  IS NULL)

',N'@id int',
@id=4395

比这个运行得更快:

exec sp_executesql N'
 SELECT [id]
 FROM [tblAddress] (nolock)
 WHERE 1 = 1
 AND ([id] = @id)

',N'@id int',
@id=4395

运行 SQL 探查器,超过 100 万行的顶级查询的持续时间是 175 并且它的读取次数为 3720,但第二个查询的持续时间为 1,并且只有 3 次读取。

为什么会出现这样的差异以及如何改进?

I'm calling some parametrized sql from .net. I'm not sure why but the sql runs quite slow when checking if the parameter is NULL compared to when its not included:

So this:

exec sp_executesql N'
 SELECT [id]
 FROM [tblAddress] (nolock)
 WHERE 1 = 1
 AND ([id] = @id OR @id  IS NULL)

',N'@id int',
@id=4395

Runs quicker then this:

exec sp_executesql N'
 SELECT [id]
 FROM [tblAddress] (nolock)
 WHERE 1 = 1
 AND ([id] = @id)

',N'@id int',
@id=4395

Running SQL profiler the duration of the top query over 1 million rows is 175 and its reads are 3720 but the second query's duration is 1 and only 3 reads.

Why such a difference and how could it be improved?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

于我来说 2024-11-02 22:58:55

OR 子句不是 SARGABLE,因此使用的计划有一个扫描,而不是像第二个那样的查找

尝试这个:2 查找

SELECT [id]
 FROM [tblAddress]
 WHERE [id] = @id
UNION ALL
SELECT [id]
 FROM [tblAddress] 
 WHERE @id IS NULL)

注意:您不需要 NOLOCK 提示。或者1=1

An OR clause isn't SARGABLE so the plan used has a scan, not a seek like the 2nd one

Try this: 2 seeks

SELECT [id]
 FROM [tblAddress]
 WHERE [id] = @id
UNION ALL
SELECT [id]
 FROM [tblAddress] 
 WHERE @id IS NULL)

Note: you don't need the NOLOCK hint. Or 1=1

烟凡古楼 2024-11-02 22:58:55

如果 @id 为 NULL,则无法进行 SEEK,因此它将始终扫描,并且总是很慢(取决于 [tblAddress] 中的行数。为了解决这个问题,您可能需要限制数量结果,由您的查询通过指定 TOP(N) 子句返回。

所以我要做的是:

IF @id IS NOT NULL
BEGIN
    SELECT [id]
      FROM [tblAddress]
     WHERE [id] = @id
END
ELSE
BEGIN
    SELECT TOP(20) [id] FROM [tblAddress] 
END

另外,如果不是严格要求的话,我不会使用 NOLOCK 提示。

There is no way you can make it to SEEK if @id is NULL, so it will always SCAN, and will always be slow (depending on the amount of rows in [tblAddress]. To fight this, you might want to limit the amount of results, returned by your query by specifying the TOP(N) clause.

So what I would do is:

IF @id IS NOT NULL
BEGIN
    SELECT [id]
      FROM [tblAddress]
     WHERE [id] = @id
END
ELSE
BEGIN
    SELECT TOP(20) [id] FROM [tblAddress] 
END

Also, I wouldn't use the NOLOCK hint if it is not strictly reuired.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文