简体   繁体   English

使用函数的SQL Server查询非常慢

[英]Very Slow SQL Server Query using Functions

This sort of follows on from a previous question: 从上一个问题开始,可以遵循以下这类方法:

SQL Server Query time out depending on Where Clause SQL Server查询超时取决于Where子句

In which a query would run extremely slowly depending on a where clause. 根据where子句,查询将在其中极其缓慢地运行。 I rewrote that query use CTE and avoided the problem nicely, but never found an answer. 我改写了使用CTE的查询,很好地避免了该问题,但从未找到答案。

Another, similar, query was tweaked recently to add another field, and suddenly it's performance dropped from taking about ~30 seconds to run and return 10,000 rows, to taking over 10 hours (and eventually returning the same result set). 最近又对另一个类似的查询进行了调整,以添加另一个字段,突然,它的性能从大约30秒的运行时间并返回10,000行返回到超过10个小时(最终返回相同的结果集)。 Today I started to troubleshoot this one and found something weird. 今天,我开始对这一问题进行故障排除,发现有些奇怪的地方。

I am constantly needing to extract the date only part from datetime values, and so I wrote the logic into a function: 我一直需要从datetime值中仅提取日期部分,因此我将逻辑写入函数:

CREATE FUNCTION [dbo].[cDate] ( @pInputDate    DATETIME )
RETURNS DATETIME
BEGIN
        RETURN CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME)
END
GO

I found in this new, inefficient query that if I replaced that function with the CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME) inline in the query, the speed of the query execution dropped from ~10 hours, to just under 2 seconds. 我在这个效率低下的新查询中发现,如果我在查询中内联CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME)替换该函数,则查询执行的速度从10个小时左右下降,不到2秒 I can see no difference in the estimated execution plan. 我看不出预计的执行计划有什么不同。 By the way, this was not the field that was added. 顺便说一句,这不是添加的字段。 I assume adding the other field somehow caused the execution plan to change and amplified the above condition. 我假设添加其他字段以某种方式导致执行计划更改并放大了上述条件。

My question is, is this normal? 我的问题是,这正常吗? I make use of functions for repetitive processes, as above, as they are easier to maintain, remember and to update if you find a more efficient way of doing something. 如上所述,我将这些功能用于重复性过程,因为如果您发现一种更有效的处理方式,它们将更易于维护,记忆和更新。 Should I be doing something to my functions to improve their performance? 我应该对功能进行一些改进以提高其性能吗?

If you must encapsulate this in a function see Scalar functions, inlining, and performance: An entertaining title for a boring post 如果必须将其封装在函数中,请参阅标量函数,内联和性能:无聊的帖子的有趣标题

Rewrite it as follows 如下重写

CREATE FUNCTION dbo.cDate_Inline
(
    @pInputDate DATETIME
)
RETURNS TABLE
AS
    RETURN
    (
        SELECT DATEADD(day, DATEDIFF(Day, 0, @pInputDate), 0) AS [Date]
    )

Then instead of 然后代替

SELECT *,
       [dbo].[cDate](modify_date) AS modified
FROM   sys.objects 

Use 采用

SELECT *,
       ca.Date AS modified
FROM   sys.objects
       CROSS APPLY dbo.cDate_Inline(modify_date) ca 

This will be inlined into the plan by the query optimiser. 这将由查询优化程序内联到计划中。

I would try possibly adding another variable to do the declaration and return. 我可能会尝试添加另一个变量来进行声明并返回。 The thought process for this could be that your cast and converting to alter the datetime for your input may be the bottleneck. 这种想法的过程可能是您的转换和转换以更改输入的日期时间可能是瓶颈。 This may not be the case but often if you set in the scope a new variable, do your conditioning and bind it to that variable and return that, that may help out with speed. 可能并非如此,但是通常如果您在范围中设置了一个新变量,请进行条件处理并将其绑定到该变量,然后将其返回,这可能有助于提高速度。 I tend to stay away from scalar functions when possible though, they have lots of performance issues when you start using them with larger data sets. 我倾向于尽可能避免使用标量函数,当您开始将它们与较大的数据集一起使用时,它们会遇到很多性能问题。 Just a suggestion it may or may not help but it would isolate the return to a new object independent of the input: 只是一个建议,它可能有帮助,也可能没有帮助,但它会将返回的结果隔离到与输入无关的新对象上:

CREATE FUNCTION [dbo].[cDate] ( @pInputDate    DATETIME )
RETURNS DATETIME
BEGIN
Declare @Output datetime  = CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME)  -- 2008 method and newer

Declare @Output datetime;

Select @Output  = CAST(CONVERT(VARCHAR(10), @pInputDate, 111) AS DATETIME)  -- 2005 and prior method 


return @Output
END
GO

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM