Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
用于大型表的MSSQL游标无法分配空间_Sql_Sql Server_Allocation_Cursors - Fatal编程技术网

用于大型表的MSSQL游标无法分配空间

用于大型表的MSSQL游标无法分配空间,sql,sql-server,allocation,cursors,Sql,Sql Server,Allocation,Cursors,我们正试图设置一个游标,以遍历由同一个大型表的两个“实例”之间的连接生成的记录(超过150m条记录) 出现以下异常消息: 无法为数据库“tempdb”中的对象“dbo.SORT临时运行存储:165282123350016”分配空间,因为“主”文件组已满。通过删除不需要的文件、删除文件组中的对象、向文件组添加其他文件或为文件组中的现有文件启用自动增长来创建磁盘空间 你们当中有人知道原因吗?或者如何使下面的查询更有效 我发现它发生在声明游标和下一次第一次获取之间,但我还不知道它是否介于 声明游标并打

我们正试图设置一个游标,以遍历由同一个大型表的两个“实例”之间的连接生成的记录(超过150m条记录)

出现以下异常消息:

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

你们当中有人知道原因吗?或者如何使下面的查询更有效

我发现它发生在声明游标和下一次第一次获取之间,但我还不知道它是否介于

声明游标并打开 或介于

打开第一个,然后取下一个。 更多详细信息: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作为包含列。执行计划不再包含任何排序,执行计划中的步骤数不到原始计划的一半,我希望这也会更快

你们当中有人知道原因吗?或者如何使下面的查询更有效

您的查询使用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

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

为什么要使用光标?尤其是在一张大桌子上?你在做什么,不能根据设定来做?CURSPR对性能极为不利,如果存在其他替代方案,则不应使用CURSPR。如果您正在根据select找到的记录插入到另一个表中,则无需光标即可完成更好的操作。

谢谢您的评论。我在问题中添加了精确的查询。目前,我在相同的列上有一个非聚集索引,但顺序不同:iBatchNumber、sFieldName、sTableName、iRowIndex。此外,当前索引还包括sFieldValue列。我应该添加您建议的索引,然后保留现有索引还是删除现有索引?您的现有索引没有帮助,因为您没有在sFieldName上筛选MD。如果您更改帖子中显示的WHERE条件,您现有的索引将起作用。这里重要的不是光标,而是索引不友好的查询。谢谢您的评论。我还没有找到一种方法将每行的多行逻辑转换成一条语句。如果我想加速的话,我可能想调查一下。。。