面对 无法为数据库'TEMPDB'分配新页,因为文件组'DEFAULT'中的磁盘空间不足



由于filegroup'default'中的磁盘空间不足,因此无法分配数据库'tempdb'的新页面。通过将对象放在文件组中,将其他文件添加到文件组中或为FileGroup中的现有文件设置自动化来创建必要的空间。

执行具有近2.5亿条记录的某些语句的存储过程时,面临此错误。

即使我在tempdb中有大约650GB的空间,但面临此错误。想知道我可以在这方面做些什么

查询:

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

tempdb不是问题。

查询具有多个具有不可降低表达式的过滤器。所有连接都必须在可以过滤的任何Where子句数据之前处理。如果您的最终结果(过滤和分组)为2.5亿行,我希望在连接率较高的数十亿美元之后的结果。在发生过滤和分组之前,必须将该结果构成。

尝试将此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

尝试以下更改,我希望您会完全避免使用肿的tempdb。

我可以看到查询的一些问题,这会使其效率低下:

  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)参数。

  1. 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)
         )

最新更新