SQL кросс-соединение на временную таблицу медленные результаты - PullRequest
1 голос
/ 23 января 2012

Добавили следующий код в мой запрос SQL: (Примечание: урезанная версия)

DECLARE @rowType AS TABLE (
    rowTypeLabel NVARCHAR (20));

INSERT  INTO @rowType
VALUES ('Cumulative');

INSERT  INTO @rowType
VALUES ('Non-Cumulative');

--select * from @rowType


SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky CROSS JOIN @rowType
WHERE  (rowTypeLabel = 'Cumulative'
        OR (rowTypeLabel = 'Non-Cumulative'
            AND (EndDate IS NULL
                 OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

Время выполнения увеличилось с 10 минут до 1 часа, есть ли у кого-нибудь какие-либо предложения относительно того, почему этоможет быть, результаты без этого перекрестного соединения были около 46 000 и после этого возвращает еще 231 строку (все, что классифицируется как «некумулятивное» согласно запросу.

Ответы [ 3 ]

4 голосов
/ 23 января 2012

Я предполагаю, что это очень упрощенный пример? Поэтому я не могу дать вам конкретику, но простой ответ заключается в том, что кумулятивная часть запроса выполняет гораздо больше работы, чем не кумулятивная часть.

Попробуйте эти два для сравнения ...

SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky

И ...

SELECT ID,Name,StartDate,
       EndDate,
       rowTypeLabel AS Period
FROM   dbo.sicky
WHERE  EndDate IS NULL
       OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

Последнее, я ожидаю, займет намного больше времени.

1011 *
*

Кроме того, условия OR для объединения нескольких частей бизнес-логики могут быть довольно сложными для оптимизатора. Это означает, что следующая структура может быть более эффективной ...

SELECT * FROM <non cumulative query>
UNION ALL
SELECT * FROM <cumulative query>
1 голос
/ 23 января 2012

Я не понимаю, зачем вам здесь нужна конструкция CROSS JOIN - это просто запутывает проблему. Я бы переписал запрос так:

SELECT ID, Name, StartDate, EndDate, 'Cumulative' AS Period
FROM   dbo.sicky
UNION ALL
SELECT ID, Name, StartDate, EndDate, 'Non-Cumulative' AS Period
FROM   dbo.sicky
WHERE EndDate IS NULL
    OR EndDate BETWEEN CAST (DateAdd(Day, 1 - Day(getDate()), getdate()) AS DATE) AND CAST (DateAdd(month, 1, DateAdd(Day, -Day(getDate()), getdate())) AS DATE))));

Это должно быть эквивалентным, но иллюстрирует, что вы делаете более четко. Предполагая, что первая часть этого UNION - это то, что у вас было раньше, а вторая - медленная, вполне вероятно, что EndDate (или любой другой эквивалент в вашем реальном запросе) не проиндексирован должным образом и вызывает чрезмерное сканирование. Разместите планы выполнения для более подробного анализа.

0 голосов
/ 23 января 2012

46000 строк за 10 минут для простого SELECT без JOIN или подзапросов ... это кажется слишком много. Убедитесь, что вы создали и включили индексы для StartDate и EndDate. Если так, я иду с mwigdahl o Dems ответы.

...