0

几年前有人在工作中进行了此更新并且它有效,问题是在一个进程中多次调用它需要将近 5 个小时,这不是常规更新,表之间没有 1 对 1 的记录匹配,这是一个基于同一个表中的 parituclar 字段的累积 (SUM) 进行更新,事情变得更加复杂,因为这个 SUM 仅限于基于日期和另一个字段的特殊条件。

我认为这类似于(隐式)内部联接,没有 1 对 1 匹配,例如 ALL VS ALL,因此当表中有 7000 条记录时,这个东西将处理 7000 * 7000 条记录,超过 5500 万条,在我的意见游标应该在这里使用,但现在我需要更快的速度,我认为游标不会让我到达那里。

我的问题是:有没有办法重写它并让它更快?注意那个 SUM 的条件,这不是一个容易看到的更新(至少对我来说)。

更多信息: 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

截图 - 执行计划

4

3 回答 3

1

从您的查询计划看来,它大部分时间都在索引假脱机之后的过滤器中花费。

如果您要运行此查询几次,我将在“CodComitente”、“CodMoneda”、“EstaAnulado”、“FechaLiquidacion”和“CodCtaCorrienteMon”列上创建一个索引。

我对 Index Spool 迭代器了解不多;但基本上据我了解,它用作在查询时创建的“临时”索引。因此,如果您多次运行此查询,我将创建一次该索引,然后根据需要多次运行查询。

另外,我会尝试创建一个变量来存储求和运算的结果,这样您就可以尽可能避免运行它。

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
于 2013-11-08T20:18:45.437 回答
0

找到了解决方案,这是一个常见问题:Running Totals

这是 CURSORS 表现更好的少数情况之一,在这里查看这个和更多可用的解决方案(或浏览 stackoverflow,有很多这样的情况):

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

于 2013-11-11T22:16:58.447 回答
0

如果没有查询计划,很难有多大帮助,但我会假设,如果 FechaLiquidacion 和 CodCtaCorrienteMon 列上还没有索引,那么只要数据库存储空间不成问题,通过创建它们就可以提高性能。

于 2013-11-08T18:15:03.290 回答