尽管手动重建查询成功,但 WHILE 循环的第一次迭代仍会耗尽内存

First iteration of WHILE loop runs out of memory despite manual reconstruction of query succeeding

提问人:Slothen 提问时间:12/14/2022 最后编辑:vvvvvSlothen 更新时间:3/3/2023 访问量:85

问:

环境:SQL Server 2019 (v15)。

我有一个大型查询,当作为单个语句运行时,它占用了太多空间。当我尝试运行它时,我收到以下错误:SELECT

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

然而,这个问题自然而然地分解成十几个部分,所以我写了一个循环来遍历每个部分并插入到结果表中。不幸的是,循环的第一次迭代也返回相同的内存错误。循环所做的只是更改子句中的一些值。WHILEWHILEWHILEWHERE

这里让我感到困惑的关键是,当我手动运行该语句的一次迭代时,在没有所有循环逻辑的情况下,它运行良好。INSERT

手动编码第一次迭代以使用第一次迭代就可以了,所以我认为这里的联接不会出错并导致内存错误。institution_name

WITH my_cte AS 
(
    SELECT [columns]
    FROM mytable a
    INNER JOIN bigtable b ON a.institution_name = b.institution_name
                          AND a.personID = b.personID
    WHERE a.institution_name = 'ABC'
      AND b.institution_name = 'ABC'
)
INSERT INTO results (personID, institution_name, ...)
SELECT personID, institution_name, [some aggregations]
FROM my_cte
GROUP BY personID, institution_name;

带有循环的版本失败。我需要使用不同的值运行查询。WHILEinstitution_name

在这里,我展示了三个不同的值,但即使只是第一次迭代也会失败。

DECLARE @INSTITUTION varchar(10)
DECLARE @COUNTER int
SET @COUNTER = 0
DECLARE @LOOKUP table (temp_val varchar(10), temp_id int)

INSERT INTO @LOOKUP (temp_val, temp_id)
VALUES ('ABC', 1), ('DEF', 2), ('GHI', 3)

WHILE @COUNTER < 3
BEGIN
    SET @COUNTER = @COUNTER + 1

    SELECT @INSTITUTION = temp_val 
    FROM @LOOKUP 
    WHERE temp_id = @COUNTER;

    WITH my_cte AS 
    (
        SELECT [columns]
        FROM mytable a
        INNER JOIN bigtable b ON a.institution_name = b.institution_name
                              AND a.personID = b.personID
        WHERE a.institution_name = @INSTITUTION
          AND b.institution_name = @INSTITUTION
    )
    INSERT INTO results (personID, institution_name, ...)
    SELECT personID, institution_name, [some aggregations]
    FROM my_cte
    GROUP BY personID, institution_name
END

在我写这个问题时,我已经复制粘贴了十几次插入语句,更改了相关子句,然后毫无错误地运行了它。这可能是某种数据类型问题,如果将字符串文字放在 WHERE 列中,则查询可以正确地子集,但由于数据类型,对我的临时表的查找失败?我注意到 is while is .设置要使用的临时表也没有修复它。WHEREmytable.institution_namevarchar(10)bigtable.institution_namenvarchar(10)nvarchar(10)

sql-server t-sql while-loop 内存不足

评论

1赞 AlwaysLearning 12/14/2022
似乎你试图优化错误的东西。与其将查询分解以使其更小,为什么不将 tempdb 文件移动到具有更多可用容量的较大存储卷中?
1赞 seanb 12/14/2022
我的猜测是,分配足够的内存/空间是一个问题,它猜测它需要进行计算 - 这很可能是对 Institution_Name 和 PersonId 的“排序”。在指定特定机构时,它可以进行更好的猜测 - 而如果它是一个变量,它需要应对任何选项。是否可以在 Institution_Name 和 PersonID 上的两个表上放置索引(两者的顺序相同)并包含您需要的其他列?如果没有,您能否在这些字段上创建一个或 #TempTables 个带有聚集索引的索引,从基表填充并以这种方式进行计算?
1赞 jigga 12/14/2022
首先你不要't 需要 AND b.institution_name = @INSTITUTION 其次,您是否使用的是 SQL Server 的 Express Edition?第三,你为什么在这里使用CTE?你可以不做...
0赞 Slothen 12/14/2022
@AlwaysLearning 我无法触及服务器的配置。但是,我认为我有证据证明分解查询应该有效,所以我真的只是想知道为什么它不起作用。
1赞 jigga 12/14/2022
恭喜!干得好:)

答: 暂无答案