2009-09-29 22 views
0

我想在同一个查询中使用相同的表函数连接多个输入变量。但是这在我的情况下比使用表变量和从表函数中分别选择要慢得多。使用表函数优化多个连接

如何避免表变量,仍然有一个快速查询?

例如,我们有像

 
SELECT P.ProjectName, A.Number, B.Number 
FROM Project AS P 
LEFT JOIN dbo.fn_ProjectNumber(@dateA) AS A 
    ON P.ProjectID = A.ProjectID 
LEFT JOIN dbo.fn_ProjectNumber(@dateB) AS B 
    ON P.ProjectID = B.ProjectID 

一个SQL查询,但它是不是从功能选择分别为变量,再后来加入,例如要慢得多:

 
INSERT INTO @tempA 
SELECT P.ProjectID, A.Number 
FROM Project AS P 
LEFT JOIN dbo.fn_ProjectNumber(@dateA) AS A 
    ON P.ProjectID = A.ProjectID 

INSERT INTO @tempB 
SELECT P.ProjectID, B.Number 
FROM Project AS P 
LEFT JOIN dbo.fn_ProjectNumber(@dateB) AS B 
    ON P.ProjectID = B.ProjectID 

SELECT P.ProjectName, A.Number, B.Number 
FROM Project AS P 
LEFT JOIN @tempA AS A 
    ON P.ProjectID = A.ProjectID 
LEFT JOIN @tempA AS B 
    ON P.ProjectID = B.ProjectID 

有什么事情是这个原因吗?有没有办法可以快速查询并避免表变量?


更多细节:

这仅仅是类似于我在做什么的例子,但功能fn_ProjectNumber(@date datetime)将包含类似四个表之间的连接......

 
+0

你不会给太多的信息继续下去。如何显示功能的代码,执行计划(SET SHOWPLAN_ALL ON)等... – 2009-09-29 14:04:20

回答

1

尝试固定的加入,你指的是错误的别名在第二LEFT JOIN:

ORIGINAL:

SELECT P.ProjectName, A.Number, B.Number 
FROM Project AS P 
LEFT JOIN dbo.fn_ProjectNumber(@dateA) AS A 
    ON P.ProjectID = A.ProjectID 
LEFT JOIN dbo.fn_ProjectNumber(@dateB) AS B 
    ON P.ProjectID = A.ProjectID 

FIXED:

SELECT P.ProjectName, A.Number, B.Number 
FROM Project AS P 
LEFT JOIN dbo.fn_ProjectNumber(@dateA) AS A 
    ON P.ProjectID = A.ProjectID 
LEFT JOIN dbo.fn_ProjectNumber(@dateB) AS B 
    ON P.ProjectID = B.ProjectID --<<<<< 
+0

啊,这是我的例子中的错误。在实际情况下,别名是正确的... – 2009-09-29 13:50:40

+0

该示例中的别名错误现在已经修复... – 2009-09-29 13:51:18

0

也许连接速度较慢,因为您尚未定义连接在一起的表之间的关系? 我不太了解SQL Server中查询的性能,但定义关系会提高连接的性能。

1

有什么特别的原因,你”重新尝试避免表变量?他们可以是一个很好的优化技术,不会留下任何临时对象来清理。

无论如何,如果你不想那样做,你总是可以尝试

SELECT 
    P.ProjectID, A.Number, B.Number 
FROM 
    Project AS P 
     LEFT JOIN 
      (SELECT P.ProjectID, A.Number 
      FROM Project AS P 
      LEFT JOIN dbo.fn_ProjectNumber(@dateA) AS A 
       ON P.ProjectID = A.ProjectID 
      ) AS A 
       ON P.ProjectID = A.ProjectID 
     LEFT JOIN 
      (SELECT P.ProjectID, B.Number 
      FROM Project AS P 
      LEFT JOIN dbo.fn_ProjectNumber(@dateB) AS B 
       ON P.ProjectID = B.ProjectID 
      ) AS B 
       ON P.ProjectID = B.ProjectID 
1

的连接是缓慢的,因为,在你的榜样查询,你一旦在表中每一行调用每个函数项目。临时表的速度更快,因为您只调用一次函数。

避免临时表的一种方法是使用CTE(通用表表达式 - 它们不仅仅适用于递归 - 在SQL 2005及更高版本中可用)。一般的语法是这样的:

WITH cteTempName (<list of columns>) 
as (<your table function call>) 
SELECT <your query here, with "cteTempName" appearing as just another table to select from> 
+0

是什么让您认为为每一行调用该函数?代码:_LEFT JOIN dbo.fn_ProjectNumber(@dateA)AS A ON P.ProjectID = A.ProjectID_看起来只被调用一次给我。 – 2009-09-29 14:09:10

+0

恩,真的。我基于这种观点,即查询运行速度比临时表的填充速度慢得多,因为通常会发生什么 - 但是你说得对,他们不应该经常被调用。慢多少?查看查询计划将很有用。 – 2009-09-29 14:29:20