Не удается выделить новую страницу для базы данных «TEMPDB» из-за недостатка места на диске в файловой группе «DEFAULT» - PullRequest
0 голосов
/ 13 марта 2019

Не удалось выделить новую страницу для базы данных 'TEMPDB' из-за недостатка места на диске в файловой группе 'DEFAULT'.Создайте необходимое пространство, отбросив объекты в файловой группе, добавив дополнительные файлы в файловую группу или установив автоматический рост для существующих файлов в файловой группе.

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

Несмотря на то, что у меня есть около 650 ГБ места в базе данных tempdb, я сталкиваюсь с этой ошибкой.Хотелось бы узнать, что я могу сделать дальше в этом

Запросе:

SELECT u.Id, u.place, u.name, u.lname, LOWER(ue.email) AS Email, MIN(dp.BirthTime) AS Time
FROM tableA u
    JOIN tableB ue ON ue.id = u.id AND ue.Did = 0
    JOIN tableC dp ON dp.Id = u.Id
        JOIN tableB dpe ON dpe.Id = dp.Id
            LEFT JOIN tableB idpe ON idpe.Email = dpe.Email
                LEFT JOIN tableE idp ON idp.Id = idpe.Id
                    LEFT JOIN tableD pidp ON pidp.Id = idp.Id 
        JOIN tableD cp ON dp.Id = cp.Id
where ISNULL(cp.FName,'') = '' AND ISNULL(cp.LName,'') = '' AND ISNULL(cp.IsActive,0) = 0 AND ISNULL(dp.Isinactive,0) = 0
    AND ISNULL(pidp.FName,'') = '' AND ISNULL(pidp.LName,'') = ''
    AND ISNULL(pidp.Isactive,0) = 0 AND ISNULL(idp.IsInactive,0)
    AND ISNULL(u.EHome, '') != ''
GROUP BY u.Id, u.Isactive, u.name, u.EServer, ue.Email

Ответы [ 2 ]

0 голосов
/ 15 марта 2019

TempDB - это не проблема.

В запросе есть несколько объединений с не-SARGable выражениями.Все объединения должны быть обработаны до того, как могут быть отфильтрованы данные предложения where.Если ваш конечный результат (отфильтрованный и сгруппированный) составляет 250 миллионов строк, я ожидаю, что результаты после объединений будут в больших миллиардах.Этот результат должен быть материализован в базе данных tempdb до того, как произойдет фильтрация и группировка.

Попробуйте изменить ISNULL(cp.FName,'') = '' на (cp.FName = '' OR cp.FName IS NULL) и все подобные выражения.Это может, по крайней мере, разрешить некоторую фильтрацию перед объединениями.

Второй шаг - удалить объединения, которые не используются в наборе результатов.Вы только возвращаете данные из таблиц U, UE & DP.Переместите другие внутренние объединения в существующие предложения

EXISTS (SELECT 1 FROM tableB dpe WHERE dpe.Id = dp.Id)

Это уменьшит начальный продукт объединения до чего-то более управляемого.

Ваши левые объединения будут более сложными для разрешения, но также не должныобъединение, если оно не является частью набора результатов.Я прочитал ваш запрос, чтобы сказать, что вы хотите отфильтровать результаты, если данные отсутствуют.Например, имя FName должно возвращаться только в том случае, если имя FName представляет собой пустую строку, нулевое значение или отсутствует соответствующая запись.Другой способ сказать, что вы не хотите видеть записи с FName, LName, IsActive, заполненные ненулевым / непустым значением.

AND NOT EXISTS ( SELECT 1 FROM tableD AS pidp where pidp.Id = idp.Id AND fname <> '' AND lname <> '' AND isactive = 0)

Этот оператор исключит их, если заполнены все 3.Если вы хотите исключить их только в том случае, если какое-либо из полей имеет значение, измените AND на OR внутри предложения EXISTS.

Попробуйте эти изменения, и я ожидаю, что вы избежите раздутогоTempDB в целом.

0 голосов
/ 15 марта 2019

Я вижу несколько проблем с запросом, которые делают его совершенно неэффективным:

  1. LEFT JOIN tableD pidp - вы оставили присоединение к этой таблице и затем применили условия фильтра в предложении WHERE:

    ISNULL(pidp.FName,'') = ''AND ISNULL(pidp.LName,'') = '' AND ISNULL(pidp.Isactive,0) = 0

ISNULL([col name], '') != '' - очень неэффективная конструкция, которая гарантирует, что любые индексы (если они есть) в столбце никогда не будут использоваться.Если столбцы не обнуляемы , переместите условия фильтра в объединение и удалите ISNULL:

ON pidp.Id = idp.Id AND pidp.FName = ''
    AND pidp.LName = '' AND pidp.Isactive = 0

Это также относится к параметру ISNULL(idp.IsInactive,0).

GROUP BY оператор для исправления проблем, вызванных слабыми соединениями / плохим дизайном запросов - это признак действительно плохого дизайна запросов и, скорее всего, единственная причина чрезмерного использования временной таблицы.

Я бы переписал запрос к чему-то вроде этого (я не включил рекомендации в Шаг 1, поскольку они зависят от вашего конкретного определения таблицы):

SELECT u.Id, u.place, u.name, u.lname, LOWER(ue.email) AS Email, MIN(dp.BirthTime) AS Time
FROM tableA u
    JOIN tableB ue ON ue.id = u.id AND ue.Did = 0
WHERE ISNULL(u.EHome, '') != ''
    AND u.Id IN(
        SELECT dp.id
        FROM tableC dp
            JOIN tableB dpe ON dpe.Id = dp.Id
                LEFT JOIN tableB idpe ON idpe.Email = dpe.Email
                    LEFT JOIN tableE idp ON idp.Id = idpe.Id
                        LEFT JOIN tableD pidp ON pidp.Id = idp.Id 
            JOIN tableD cp ON dp.Id = cp.Id
        where ISNULL(cp.FName,'') = '' AND ISNULL(cp.LName,'') = '' AND ISNULL(cp.IsActive,0) = 0 AND ISNULL(dp.Isinactive,0) = 0
            AND ISNULL(pidp.FName,'') = '' AND ISNULL(pidp.LName,'') = ''
            AND ISNULL(pidp.Isactive,0) = 0 AND ISNULL(idp.IsInactive,0)
         )
...