当前位置:  开发笔记 > 数据库 > 正文

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

如何解决《巨大的表的MSSQL游标无法分配空间》经验,为你挑选了1个好方法。

我们正在尝试设置一个游标来运行从同一个巨大表的两个"实例"之间的连接生成的记录(超过150个M记录).

出现以下异常消息:

无法为数据库'tempdb'中的对象'dbo.SORT临时运行存储:165282123350016'分配空间,因为'PRIMARY'文件组已满.通过删除不需要的文件,删除文件组中的对象,向文件组添加其他文件或为文件组中的现有文件设置自动增长来创建磁盘空间.

你们有谁知道这个的原因吗?或者如何使下面的查询更有效?

我发现它发生在介于两者之间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的更新答案之后,我还在表格上发布了原始索引:

我对这个表列一个非聚集索引iBatchNumber,sFieldName,sTableName,iRowIndex.该索引sFieldValue包含在列中.


由于Quassnoi建议(我想我明白为什么现在)我已经改变了指数有列顺序是:iBatchNumber,sTableName,iRowIndex,sFieldName.我sFieldValue用作包含的列.执行计划不再包含任何内容SORT,执行计划中的步骤数少于原始步骤的一半,我希望也更快...



1> Quassnoi..:

你们有谁知道这个的原因吗?或者如何使下面的查询更有效?

您的查询使用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使用任何操作.

推荐阅读
保佑欣疼你的芯疼
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有