2009-09-29 11 views
0

Я хотел бы присоединиться несколько раз с той же табличной функцией для разных входных переменных в том же запросе. Но в моем случае это оказывается намного медленнее, чем использование переменных таблицы и выбор из функций таблицы отдельно.Оптимизация множественных соединений с помощью табличных функций

Как избежать переменных таблицы и иметь быстрый запрос?

Например, у нас есть SQL запрос типа

 
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 

но гораздо медленнее, чем при выборе из функций отдельно в переменных, а затем присоединиться позже, например:

 
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) и т. д. –

ответ

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 

ИСПРАВЛЕНО:

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

А, это ошибка в моем примере. В этом случае псевдонимы правильны ... –

+0

Ошибка псевдонима в примере была исправлена ​​... –

0

Может быть соединения медленнее, потому что вы не определили отношения между таблицами, которые соединены вместе? Я мало знаю о производительности запросов в SQL Server, но определение отношений улучшит производительность соединений.

1

Есть ли какой-либо конкретной причине вы» re пытается избежать переменных таблицы? Они могут быть хорошей технологией оптимизации и не оставлять никаких временных объектов для очистки.

Во всяком случае, если вы не хотите, чтобы сделать это таким образом, вы всегда можете попробовать

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_ выглядит как одно время для меня. –

+0

Хм, правда.Я основывал это на утверждении о том, что запрос выполнялся намного медленнее, чем когда заполнялись временные таблицы, поскольку обычно это происходит, но вы правы, их не следует часто называть. Насколько медленнее? Видеть план запроса было бы полезно. –