2013-11-08 1 views
0

Кто-то на работе сделал это ОБНОВЛЕНИЕ несколько лет назад, и это работает, проблема в том, что он занимает почти 5 часов, когда вызывается несколько раз в процессе, это не регулярное ОБНОВЛЕНИЕ, нет записи от 1 до 1 сопоставление между таблицами, это делает обновление, основанное на накоплении (SUM) поля parituclar в той же таблице, и все усложняется, поскольку этот SUM ограничен особыми условиями на основе дат и другого поля.Оптимизация сложного SQL-обновления

Я думаю, что это что-то вроде (неявного) внутреннего соединения без соответствия 1 к 1, как ВСЕ ВС ВСЕ, поэтому, имея, например, 7000 записей в таблице, эта вещь будет обрабатывать 7000 * 7000 записей, более 55 миллион, на мой взгляд, курсоры должны были использоваться здесь, но теперь мне нужно больше скорости, и я не думаю, что курсоры меня доставят.

Мой вопрос: есть ли способ переписать это и сделать его быстрее? Обратите внимание на условия на этом SUM, это не просто увидеть UPDATE (по крайней мере, для меня).

Подробнее: CodCtaCorriente и CodCtaCorrienteMon являются первичные ключи этой таблицы, но, как я уже сказал нет намерения сделать 1 к 1 матч здесь, поэтому эти клавиши не используются в запросе, CodCtaCorrienteMon используется в условия, но не как условие соединения (ON).

UPDATE #POS SET SaldoDespuesEvento = 
    (SELECT SUM(Importe) 
     FROM #POS CTACTE2 
     WHERE CTACTE2.CodComitente = #POS.CodComitente 
     AND CTACTE2.CodMoneda = #POS.CodMoneda 
     AND CTACTE2.EstaAnulado = 0 
     AND (DATEDIFF(day, CTACTE2.FechaLiquidacion, #POS.FechaLiquidacion) > 0 
       OR 
      (DATEDIFF(day, CTACTE2.FechaLiquidacion, #POS.FechaLiquidacion) = 0 
       AND (#POS.CodCtaCorrienteMon >= CTACTE2.CodCtaCorrienteMon)))) 
WHERE #POS.EstaAnulado = 0 AND #POS.EsSaldoAnterior = 0 

ScreenShot - Execution Plan

+0

вы не возражаете давая картину плана запроса? – Martin

+0

Скриншот прилагается – Jcis

+0

Какие индексы у вас есть в таблице? Это поможет, если вы добавите оператор 'CREATE TABLE'. –

ответ

0

Трудно помочь много без плана запроса, но я хотел бы сделать предположение, что, если нет уже индексы на столбцах FechaLiquidacion и CodCtaCorrienteMon то производительность будет улучшена за счет создания их пока пространство для хранения базы данных не является проблемой.

1

Из вашего плана запроса это выглядит так, что он тратит большую часть времени в фильтре сразу после катушки индекса.

Если вы собираетесь запустить этот запрос несколько раз, я бы создал индекс в столбцах «CodComitente», «CodMoneda», «EstaAnulado», «FechaLiquidacion» и «CodCtaCorrienteMon».

Я мало знаю об Итераторе катушки индекса; но в основном из того, что я понимаю об этом, его использовали как «временный» индекс, созданный во время запроса. Поэтому, если вы выполняете этот запрос несколько раз, я бы создал этот индекс один раз, а затем запустил запрос столько раз, сколько вам нужно.

Кроме того, я бы попытался создать переменную, чтобы сохранить результат вашей операции суммирования, поэтому вы можете избежать ее как можно большего.

DECLARE @sumVal AS INT 

SET @sumVal = SELECT SUM(Importe) 
     FROM #POS CTACTE2 
     WHERE CTACTE2.CodComitente = #POS.CodComitente 
     AND CTACTE2.CodMoneda = #POS.CodMoneda 
     AND CTACTE2.EstaAnulado = 0 
     AND (DATEDIFF(day, CTACTE2.FechaLiquidacion, #POS.FechaLiquidacion) > 0 
       OR 
      (DATEDIFF(day, CTACTE2.FechaLiquidacion, #POS.FechaLiquidacion) = 0 
       AND (#POS.CodCtaCorrienteMon >= CTACTE2.CodCtaCorrienteMon))) 

UPDATE #POS SET SaldoDespuesEvento = @sumVal 
WHERE #POS.EstaAnulado = 0 AND #POS.EsSaldoAnterior = 0 
+1

Это условная сумма, означающая, что это не только 1 СУММ, столько строк SUM(), сколько строк в таблице, см. Условия дат и условие CodCtaCorrienteMon внутри внутреннего запроса, они зависят от значения во внешней записи запроса , Это не обычное обновление, оно работает как код внутри курсоров с использованием SUM(), запись по записи. – Jcis

0

Найдено решение, это общая проблема: Запуск Итоговые

Это один из немногих случаев КУРСОРЫ работать лучше, увидеть это и более доступные решения здесь (или просмотреть StackOverflow, есть много случаев, как это):

http://weblogs.sqlteam.com/mladenp/archive/2009/07/28/SQL-Server-2005-Fast-Running-Totals.aspx