2009-08-19 50 views
3

如果直接内联SQL,在SQL Server 2008中使用内联表值函数时是否存在固有成本?我们的应用程序非常大量地使用内联表值函数来重用常见查询,但是最近我们发现如果我们不使用它们,查询运行得更快。SQL Server中的内联表值函数的成本

考虑一下:

CREATE FUNCTION dbo.fn_InnerQuery (@asOfDate DATETIME) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT ... -- common, complicated query here 
) 

现在,当我这样做:

SELECT TOP 10 Amount FROM dbo.fn_InnerQuery(dbo.Date(2009,1,1)) ORDER BY Amount DESC 

查询,在约15秒的成绩返回。

然而,当我这样做:

SELECT TOP 10 Amount FROM 
(
    SELECT ... -- inline the common, complicated query here 
) inline 
ORDER BY Amount DESC 

查询返回在不到1秒。

我在这种情况下使用表值函数的开销有点困惑。我原本没想到。在我们的应用程序中,我们有很多表值函数,所以我想知道是否有我在这里失踪的东西。

回答

3

在这种情况下,应该像视图一样展开/展开UDF,并且它应该是透明的。

显然,这是不是......

在这种情况下,我的猜测是,该列是SMALLDATETIME,并转换为日期时间,因为UDF参数而是不断被正确评估(匹配科拉姆数据类型)时,一致。

日期时间具有较高的优先级是smalldatetime时,所以列将投

什么查询计划说呢?该UDF将显示扫描,内嵌一个寻求最有可能(不是100%,只是根据我以前见过)

编辑:Blog post by Adam Machanic

+0

gbn,感谢您的链接。我必须深入研究它。 看来UDF的执行计划比内联版本要复杂得多,尽管我并不清楚为什么会出现这种情况。它确实显示我如何传递参数改变了行为。 SELECT TOP 10金额FROM dbo.fn_InnerQuery(dbo.Date(2008,7,24))ORDER BY金额 在15秒内运行。 选择TOP 10 Amount FROM dbo.fn_InnerQuery('7/24/2008')ORDER BY Amount runs in less than 1. – Linus 2009-08-19 17:11:38

+0

使用'7/24/2008'然后dbo.Date会发生什么(2008, 7,24)内联? – gbn 2009-08-19 17:17:12

0

可以减慢功能的一件事是省略dbo。从函数内部的表引用。这会导致SQL Server为每个调用执行安全检查,这可能很昂贵。

+3

仅在编译/重用时间。下一次运行(相同的查询,相同的用户等),这将是好的 – gbn 2009-08-19 16:53:00

+1

我们不会遗漏dbo。所以不应该是这样。而且,即使有开销,我也不会想象这会是14秒的开销。 – Linus 2009-08-19 17:01:40

0

尝试独立运行的表值函数看,怎么快/慢执行?

此外,我不知道如何清除执行缓存(?)SQL Server可能会保留执行的UDF。我的意思是 - 如果你先运行UDF,可能会出现这样的情况,即SQL Server具有实际的查询,它可以缓存计划/结果&。因此,如果您单独运行复杂的查询 - 它可能会从缓存中运行它。

+0

清除执行缓存: DBCC FREEPROCCACHE – 2010-03-03 23:50:24

0

在第二个示例中,表值函数必须在查询可以应用过滤器之前返回整个数据集。跳过TF边界并不是优化器总是可以做到的事情。

在第三个例子中,查询优化器可以计算出用户只需要最上面的'金额'。如果这不是一个合计值,那么优化器可以将该处理权推到查询的开头,而不用担心任何其他数据。如果它是一个总额,那么放缓是出于不同的原因。

如果您比较两个查询的查询计划,您应该看到它们是不同的。

+0

这仅适用于多语句表值函数。当它发生时,你看不到内在的计划。 YOu只能从SQL探查器推断IO和CPU – gbn 2009-08-19 16:59:38