Мы пытаемся настроить курсор для запуска записей, сгенерированных из объединения двух «экземпляров» одной и той же огромной таблицы (более 150 млн записей).
Появляется следующее сообщение об исключении:
Не удалось выделить место для объекта 'dbo.SORT временное хранилище: 165282123350016' в базе данных 'tempdb', поскольку файловая группа 'PRIMARY' заполнена. Создайте место на диске, удалив ненужные файлы, удалив объекты в файловой группе, добавив дополнительные файлы в файловую группу или установив автоматический рост для существующих файлов в файловой группе.
Кто-нибудь из вас знает причину этого? Или как сделать приведенный ниже запрос более эффективным?
Я обнаружил, что это происходит где-то между DECLARE CURSOR
и первым FETCH NEXT
, но я пока не знаю, находится ли он между ...
или между
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
в качестве включенного столбца.
Как предложил Кассной (и теперь я понимаю, почему), я изменил индекс, чтобы столбцы были в следующем порядке: iBatchNumber
, sTableName
, iRowIndex
, sFieldName
. И я использую sFieldValue
в качестве включенного столбца. План выполнения больше не содержит SORT
, а количество шагов в плане выполнения составляет менее половины исходного, что, я надеюсь, также быстрее ...