We are trying to set up a cursor to run through records generated from a join between two 'instances' of the same huge table (more than 150 M records).
The following exception message comes out:
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.
Do any of you know the reason for this? Or how to make the query below below more efficient?
I have found that it occurs somewhere between DECLARE CURSOR
and the first FETCH NEXT
, but I do not know yet if it is between...
DECLARE CURSOR
andOPEN
or between
OPEN
and the firstFETCH NEXT
.
More details: The sql statement looks like:
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.
where the last log message I get is 'A' and then one hour later it fails with the message described above, never reaching 'C'. I am now trying with logging at point 'B'.
On request I post the exact sql expression:
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
After the updated answer from Quassnoi, I also post the original index on the table:
I have a nonclustered index on this table with the columns iBatchNumber
, sFieldName
, sTableName
, iRowIndex
. And that index has sFieldValue
as an included column.
As Quassnoi suggested (and I think I understand why now) I have changed the index to have the columns in this order: iBatchNumber
, sTableName
, iRowIndex
, sFieldName
. And I use sFieldValue
as an included column. The execution plan does not contain any SORT
anymore, and the number of steps in the execution plan is less than half of original, which I hope is also faster...