Сравнение производительности: полное внешнее соединение против Union, Union All - PullRequest
1 голос
/ 17 июня 2011

У меня есть таблицы с именами:

mktActualsales (SaleID, EmployeeID, PeriodID,PositionID)
 mktActualSalesItems(SaleItemID, saleID, Item, Quantity)
 mktSalesTargets(TargetID, EmployeeID, PeriodID,PositionID)
 mktSalesTargetItems(TargetITemID, TargetID,ItemID, Quantity )
 sysPeriods(PeriodID, StartDate, EndDate) 

Взаимосвязи между таблицами sale и saleDetails, описанными выше, очевидны, а SaleID, а Target и TargetDetail связаны через TargetID. То, что я хочу показать, это продажи сотрудников и цели во все периоды Есть периоды, когда продажи отсутствуют, а в других периодах цели могут отсутствовать.

Мой план (до сих пор) состоит в том, чтобы использовать внутреннее объединение sale и saleDetail в одном подзапросе, target и targetDetail в другом подзапросе, а затем полное внешнее объединение в обоих подзапросах дает мне необходимые данные. Но результат очень медленный. что я могу сделать, чтобы ускорить производительность. Я нашел Google для сравнения производительности между полным внешним объединением и объединением, но мне не повезло. В настоящее время я понятия не имею, можно ли достичь желаемого результата с помощью Union / Union All.

Редактировать

Это мой запрос. Также отредактировал таблицы

SELECT  sale.ActualSaleID, 
        COALESCE (sale.EmployeeID, saleTarget.EmployeeID) AS EmployeeID, 
        COALESCE (sale.PositionID, saleTarget.PositionID) AS PositionID, 
        COALESCE (sale.PeriodID, saleTarget.PeriodID) AS PeriodID, 
        COALESCE (sale.SKUID, saleTarget.SKUID) AS SKUID, 
        COALESCE (sale.SalesQuantity, 0) AS SalesQuantity, 
        saleTarget.SalesTargetID, 
        COALESCE (saleTarget.TargetQuantity, 0) AS TargetQuantity, 
        saleTarget.SalesTargetItemID, 
        sale.ActualSaleItemID, 
        p.StartDate, 
        p.EndDate
FROM (
        SELECT  s.ActualSaleID, 
                s.EmployeeID, 
                s.PeriodID, 
                s.PositionID, 
                si.ActualSaleItemID, 
                si.SKUID, 
                si.SalesQuantity
        FROM dbo.mktActualSaleItems AS si 
            INNER JOIN dbo.mktActualSales AS s 
                ON si.ActualSaleID = s.ActualSaleID
    ) AS sale 
    FULL OUTER JOIN
    (
        SELECT  t.EmployeeID, 
                t.PeriodID, 
                t.PositionID, 
                t.SalesTargetID, 
                ti.SKUID, 
                ti.TargetQuantity, 
                ti.SalesTargetItemID
        FROM dbo.mktSalesTargetItems AS ti 
            INNER JOIN dbo.mktSalesTargets AS t 
                ON t.SalesTargetID = ti.SalesTargetID
    ) AS saleTarget 
        ON sale.PeriodID = saleTarget.PeriodID 
        AND sale.PositionID = saleTarget.PositionID 
        AND sale.SKUID = saleTarget.SKUID 
    INNER JOIN dbo.sysPeriods AS p 
        ON p.PeriodID = COALESCE (sale.PeriodID, saleTarget.PeriodID)

Ответы [ 2 ]

1 голос
/ 17 июня 2011

Я думаю, у вас есть ошибка в запросе - ваше объединение между SALE и SALETARGET не включает столбец employeeID.COALESCE скрывает это, но я думаю, что вы получаете гораздо больше строк, чем вам нужно ...

Однако, способ ускорить запросы - сначала понять, почему они медленные;план выполнения - путь.Используйте Query Analyzer, чтобы сообщить вам, что происходит - вы используете индексы для всех объединений?Перепишите запрос, чтобы использовать операторы объединения, только если вы исчерпали все параметры текущей реализации.

Что касается стиля, я не думаю, что нужно использовать COALESCE для столбцов, к которым вы присоединяетесь - они никогда не могут быть нулевыми, и это обычно скрывает ошибки.

1 голос
/ 17 июня 2011

Я не думаю, что вам нужен подзапрос, вы можете сделать то же самое в одном запросе

SELECT  s.ActualSaleID, 
        COALESCE (s.EmployeeID, t.EmployeeID) AS EmployeeID, 
        COALESCE (s.PositionID, t.PositionID) AS PositionID, 
        COALESCE (s.PeriodID, t.PeriodID) AS PeriodID, 
        COALESCE (si.SKUID, ti.SKUID) AS SKUID, 
        COALESCE (si.Quantity, 0) AS SalesQuantity, 
        t.TargetID, 
        COALESCE (ti.Quantity, 0) AS TargetQuantity, 
        ti.TargetITemID, 
        si.SaleItemID, 
        p.StartDate, 
        p.EndDate
FROM dbo.mktActualSales AS s 
        INNER JOIN dbo.mktActualSaleItems AS si 
            ON si.ActualSaleID = s.ActualSaleID
    FULL OUTER JOIN dbo.mktSalesTargets AS t 
        ON s.PeriodID = t.PeriodID 
        AND s.PositionID = t.PositionID 
        AND si.SKUID = ti.SKUID 
            INNER JOIN dbo.mktSalesTargetItems AS ti 
                ON t.SalesTargetID = ti.SalesTargetID
    INNER JOIN dbo.sysPeriods AS p 
        ON p.PeriodID = COALESCE (s.PeriodID, t.PeriodID)

Я не уверен насчет именования полей, но вы поняли идею.

Это может ускорить запрос.

Не забудьте также проверить индексы !!

...