sql - 巨大表的 MSSQL 游标无法分配空间

标签 sql sql-server allocation cursors

我们正在尝试设置一个游标来遍历同一巨大表(超过 1.5 亿条记录)的两个“实例”之间的连接生成的记录。

出现如下异常信息:

Could not allocate space for object 'dbo.SORT temporary run storage: 165282123350016' in database 'tempdb' because the 'PRIMARY' filegroup is full. Create disk space by deleting unneeded files, dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup.

你们知道这是什么原因吗?或者如何让下面的查询更高效?

我发现它发生在 DECLARE CURSOR 和第一个 FETCH NEXT 之间的某处,但我还不知道它是否介于...

  • DECLARE CURSOROPEN

或之间

  • OPEN 和第一个 FETCH NEXT

更多细节:sql语句如下:

DECLARE cData CURSOR LOCAL FORWARD_ONLY READ_ONLY
FOR
  SELECT ...
  FROM HugeTable HT1 JOIN HugeTable HT2 ON .. 
  JOIN Table3 ON .. JOIN Table4 ON .. JOIN Table5 ON ..
  WHERE ...
  ORDER BY HT1..., HT1...

INSERT INTO SysLog (Description) VALUES ('A')

OPEN cData
BEGIN TRANSACTION ProcessData
  -- Currently trying new logging here:
  -- INSERT INTO SysLog (Description) VALUES ('B') 
  FETCH NEXT FROM cData INTO ...
  INSERT INTO SysLog (Description) VALUES ('C')
  ... etc.

我收到的最后一条日志消息是“A”,然后一小时后它失败并显示上述消息,从未到达“C”。我现在正在尝试在“B”点进行日志记录。


根据要求,我发布了准确的 sql 表达式:

DECLARE cSource CURSOR LOCAL FORWARD_ONLY READ_ONLY
FOR
    SELECT MD.sFieldName, 
        MD.sFieldValue, 
        TR.sTargetDataType,
        MD2.sFieldValue AS sUniqueID,
        TR.sTargetTableName,
        TR.sTargetFieldName,
        I.iRefCustomerID, 
        I.iInterfaceID, 
        IL.iRefInterfaceSessionID
    FROM MasterData MD
    JOIN MasterData MD2
        ON MD.iRowIndex = MD2.iRowIndex
        AND MD.iBatchNumber = MD2.iBatchNumber
        AND MD.sTableName = MD2.sTableName 
        AND MD2.sFieldName = 'sUniqueID'
    JOIN SourceTargetRelation TR
        ON MD.sFieldName = TR.sSourceFieldName
        AND MD.sTableName = TR.sSourceTableName
    JOIN InterfaceLog IL
        ON IL.iInterfaceLogID = MD.iBatchNumber
    JOIN Interface I
        ON I.iInterfaceID = IL.iRefInterfaceID
        AND TR.iRefSystemID = I.iRefSystemID
    WHERE
        MD.iBatchNumber = @iBatchNumber
    ORDER BY MD.sTableName, MD.iRowIndex

在 Quassnoi 的更新答案之后,我也将原始索引发布在表格上:

我在该表上有一个非聚集索引,其中包含列 iBatchNumbersFieldNamesTableNameiRowIndex。该索引将 sFieldValue 作为包含的列。


正如 Quassnoi 所建议的(我想我现在明白为什么了)我已经更改了索引以具有以下顺序的列:iBatchNumbersTableNameiRowIndex 字段名。我使用 sFieldValue 作为包含的列。执行计划不再包含任何SORT,并且执行计划中的步骤数不到原来的一半,我希望也更快......

最佳答案

Do any of you know the reason for this? Or how to make the query below below more efficient?

您的查询使用 ORDER BY

这需要排序,排序需要临时空间。你不在这个空间内。

为避免这种情况,请在您的大表上创建一个复合索引:(col_filter_1, col_filter_2, col_order_1, col_order_2),其中 col_filter_n 是您筛选的列,并且col_order_n 是您排序的列。

这样的索引可用于过滤和排序过滤结果。

如果您发布您的实际查询(即您过滤和排序的表达式),我可能会更准确地告诉您如何创建这样的索引。

更新:

从您的查询中,我可以看出您需要 (iBatchNumber, sTableName, iRowIndex, sFieldName) 上的索引(按此顺序)。

如果您使 MD2 在连接中处于领先地位,它也可能会有所帮助:

WHERE
    MD2.iBatchNumber = @iBatchNumber
ORDER BY
    MD2.sTableName, MD2.iRowIndex

查看执行计划并确保未使用SORT 操作。

关于sql - 巨大表的 MSSQL 游标无法分配空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/709333/

相关文章:

sql-server - 使用 CFDUMP 查看时的二进制数据不同

sql-server - 允许的公共(public)表表达式 (CTE) 表达式的数量是否有限制?

c++ - 没有堆栈分配整个程序编译?

mysql - SQL调优: division between the sum of two columns

sql - 如何在多个联接行之间强制执行 SQL 联接条件?

sql - 多对多关系 JOIN 的研究

c# - 遍历记录并根据条件更新数据库

c - [C]结构体动态分配内存,与GTK相关

objective-c - 这有多糟糕?在 30 秒内分配了 3GB 总字节数

php - 未知专栏?