似乎 SQL Server 无法按函数结果进行搜索。有什么办法吗?



我创建了两个表,我们称它们为 foobar。两张表都包含一个数字。foo在此列上具有索引。foo包含大量的行,而bar只有少数行。然后我写

select * 
from foo 
where number in (select number from bar)

正如我期望的那样,此查询执行非常快。它找到了我在bar中拥有的3个记录,即使FOO有80,000多个记录,它也对这三个值进行了索引,并以一秒钟的时间返回结果。

然后,我编写了一个函数"回声",除了将整数作为参数并返回整数,即回声的整个文本为" return @x"。

然后我尝试此查询:

select * 
from foo 
where number in (select dbo.echo(number) from bar)

使用完全相同的数据,此查询要慢得多。当我检查查询计划时,事实证明第一个查询使用索引快速查找所选记录,但是第二个查询却没有,而是对整个表进行顺序搜索。

请注意,这与我们使索引无用的查询不同。就像我说的那样,"哪里dbo.echo(number(= 42",那么当然,数字的索引现在毫无用处(大概是DB引擎不知道该函数只是返回其输入,因为这样的函数在现实生活中将是没有用的,我并不感到惊讶,它们不会在特殊处理中构建(,因此,数据库引擎别无选择,只能依次搜索整个桌子。但是在这里,它在bar上的字段上执行功能。然后,它应该能够在foo上的索引中查看该值,就像我给出的值未包装在函数中一样。

为什么?更重要的是,有什么办法解决这个问题吗?当然,导致该实验的真正问题是一个功能,它不仅可以返回其参数,而且实际上是在进行一些解密。但是我在这里的实验证明,仅使用功能削弱了查询计划。

这是我实验的实际表:

CREATE TABLE [dbo].[foo]
(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [name] [varchar](50) NULL,
    [number] [int] NULL,
    PRIMARY KEY CLUSTERED ([id] ASC)
)
CREATE INDEX [ix_foo_number] ON [dbo].[foo] ([number] ASC)
CREATE TABLE [dbo].[bar]
(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [number] [int] NULL,
    [some_value] [varchar](10) NULL,
    PRIMARY KEY CLUSTERED ([id] ASC)
)
create function [dbo].[echo](@x int) returns int
as
begin
    return @x
end

然后,我用82,000个记录和3个记录填充了FOO。

查询是:

select * from foo where number in (select number from bar)
select * from foo where number in (select dbo.echo(number) from bar)
第一个查询的计划成本为0.025,第二个查询成本为0.848。超过30倍的成本,因为我添加了一个没有功能的功能。好的,仍然很小,但是在促使此促成的实际查询中,成本飙升至500多个,导致了超过500的时间。

我可以将您推荐给此出色的博客文章,该文章讨论了SQL Server中标量功能的性能问题:

T-SQL用户定义的功能:好,坏和丑陋(第1部分(

请注意,还有一些其他部分可以详细介绍。

从上面的评论中添加:

优化器基本上不假定任何事情。因此,即使有三个值,也不知道。为了比较它,它将为每个记录调用该功能,因此在您的情况下进行82,000次。它不"知道"结果是确定性的。它不"知道"结果不会随着每个执行而发生变化(例如,getDate((做(。因此,它不是也不能"缓存"它。

您可以尝试定义"使用Schemabinding"定义功能,看看是否有任何效果...我知道在某些情况下确实如此,但这还没有真正帮助我。我不完全理解这里的细微差别,因为我已经看到使用函数的地方要快得多,但是在大多数情况下,它要慢得多。

在第一个选择中,您可以使用清晰的值进行条件,但是在第二个查询中,服务器必须执行3台函数,此后,将函数的结果用于条件。

这很慢,因为您向后做事。当您搜索解密的值时,发动机别无选择,只能从表中的每个行解密值以进行比较。有关索引的类似讨论,请参阅SQL Server中的加密列索引 - 这可能是您需要解决的下一步。而且,如果您在"搜索加密列"一词上搜索您将进行许多其他讨论 - 如果加密是主要问题,则有些非常重要的讨论。

相关内容

  • 没有找到相关文章

最新更新