通过加入子查询提高更新的性能

时间:2021-04-05 14:01:57

标签: sql-server join

我有一个大型数据库,我每天都会在其中运行更新以更新前一天的活动。下面的更新工作正常,虽然它真的很慢:当我有超过 1000 条记录要更新时,它可能需要超过 40 秒。请注意,它是运行 9x 的相同子查询,只是为了更新 1 条记录的列。我知道使用连接可以提高性能,尽管我的 SQL 技能有限,虽然我尝试过但没有成功。

我想知道是否有人可以帮助转换!

这是代码:

更新接收 2 个变量:@Arg_ID_cartera@Arg_UID_pr

update gestor_val_pos 
        set cantidad = (select top 1 gestor_transac.shabal from gestor_transac 
                      where CONVERT(date,gestor_transac.fecha_tran) <= 
                      CONVERT(date,gestor_val_pos.fecha_trade) and gestor_transac.uid_producto= 
                      gestor_val_pos.uid_producto and id_cartera= @Arg_ID_cartera
                      order by gestor_transac.fecha_tran desc
                     )
        , coste_div_loc = (select top 1 gestor_transac.Coste_LOC_BAL from gestor_transac 
                      where CONVERT(date,gestor_transac.fecha_tran) <= 
                      CONVERT(date,gestor_val_pos.fecha_trade) and gestor_transac.uid_producto= 
                      gestor_val_pos.uid_producto and id_cartera= @Arg_ID_cartera
                      order by gestor_transac.fecha_tran desc
                     )
         ,  coste_div_car = (select top 1 gestor_transac.Coste_CAR_BAL from gestor_transac
                      where CONVERT(date,gestor_transac.fecha_tran) <= 
                      CONVERT(date,gestor_val_pos.fecha_trade) and gestor_transac.uid_producto= 
                      gestor_val_pos.uid_producto and id_cartera= @Arg_ID_cartera 
                      order by gestor_transac.fecha_tran desc
                     ) 
        ,  POS_cum_Inflows = (select top 1 gestor_transac.TRAN_Cum_inflows from gestor_transac 
                     where CONVERT(date,gestor_transac.fecha_tran) <= 
                     CONVERT(date,gestor_val_pos.fecha_trade) and gestor_transac.uid_producto= 
                     gestor_val_pos.uid_producto and id_cartera= @Arg_ID_cartera
                     order by gestor_transac.fecha_tran desc
                     )    
        ,  POS_cum_Outflows = (select top 1 gestor_transac.TRAN_Cum_Outflows from gestor_transac 
                      where CONVERT(date,gestor_transac.fecha_tran) <= 
                      CONVERT(date,gestor_val_pos.fecha_trade) and gestor_transac.uid_producto= 
                      gestor_val_pos.uid_producto and id_cartera= @Arg_ID_cartera
                      order by gestor_transac.fecha_tran desc
                     )    
        ,  Descripcion = (select top 1 gestor_transac.descrpcion from gestor_transac 
                      where CONVERT(date,gestor_transac.fecha_tran) <= 
                      CONVERT(date,gestor_val_pos.fecha_trade) and gestor_transac.uid_producto= 
                      gestor_val_pos.uid_producto and id_cartera= @Arg_ID_cartera order by 
                      gestor_transac.fecha_tran desc
                     ) 
        , Custodio = (select top 1 gestor_transac.custodio from gestor_transac 
                      where CONVERT(date,gestor_transac.fecha_tran) <= 
                      CONVERT(date,gestor_val_pos.fecha_trade) and gestor_transac.uid_producto= 
                      gestor_val_pos.uid_producto and id_cartera= @Arg_ID_cartera order by 
                      gestor_transac.fecha_tran desc
                     )
        , Fecha_compra = (select top 1 gestor_transac.fecha_tran from gestor_transac 
                      where CONVERT(date,gestor_transac.fecha_tran) <= 
                      CONVERT(date,gestor_val_pos.fecha_trade) and gestor_transac.uid_producto= 
                      gestor_val_pos.uid_producto and id_cartera= @Arg_ID_cartera order by 
                      gestor_transac.fecha_tran desc
                     )
        , Fecha_vencimiento = (select top 1 gestor_transac.fecha_vencimiento from gestor_transac 
                      where CONVERT(date,gestor_transac.fecha_tran) <= 
                      CONVERT(date,gestor_val_pos.fecha_trade) and gestor_transac.uid_producto= 
                      gestor_val_pos.uid_producto and id_cartera= @Arg_ID_cartera order by 
                      gestor_transac.fecha_tran desc
                     )
where id_cartera= @Arg_ID_cartera and uid_producto= @Arg_UID_pr;

2 个答案:

答案 0 :(得分:1)

我不知道列表的类型。您必须更改参数类型。

您可以通过一个执行查询并使用参数更新列来声明和设置主表中的参数。

试试这个:

------------------------------------**Main Parameter**-------------------------        
-- you can create procedure with main parameter and exec procedure
DECLARE @Arg_ID_cartera bigint --*Set This Value*-- --(int, uniqueidentifier , ... i dont know type)
DECLARE @Arg_UID_pr uniqueidentifier--*Set This Value*----(int, bigint , ... i dont know type)

------------------------------------**gestor_val_pos Parameter**-------------------------     
DECLARE @fecha_trade bigint--(int, nvarchar(500) , ... i dont know type)
DECLARE @uid_producto uniqueidentifier--(int, nvarchar(500) , ... i dont know type)

------------------------------------**Update Parameter**-------------------------  
DECLARE @shaba nvarchar(500) --(int, uniqueidentifier , ... i dont know type)
DECLARE @Coste_LOC_BAL nvarchar(500) --(int, uniqueidentifier , ... i dont know type)
DECLARE @Coste_CAR_BAL nvarchar(500) --(int, uniqueidentifier , ... i dont know type)
DECLARE @TRAN_Cum_inflows nvarchar(500) --(int, uniqueidentifier , ... i dont know type)
DECLARE @TRAN_Cum_Outflows nvarchar(500) --(int, uniqueidentifier , ... i dont know type)
DECLARE @descrpcion nvarchar(500) --(int, uniqueidentifier , ... i dont know type)
DECLARE @custodio nvarchar(500) --(int, uniqueidentifier , ... i dont know type)
DECLARE @fecha_tran nvarchar(500) --(int, uniqueidentifier , ... i dont know type)
DECLARE @fecha_vencimiento nvarchar(500) --(int, uniqueidentifier , ... i dont know type)
   
------------------------------------**Set gestor_val_pos parameter **-------------------------   
SELECT @fecha_trade = g.fecha_trade, @uid_producto = g.uid_producto
FROM  gestor_val_pos  g
WHERE id_cartera = @Arg_ID_cartera and uid_producto= @Arg_UID_pr;

------------------------------------**@shaba , @Coste_LOC_BAL , @Coste_CAR_BAL, @TRAN_Cum_inflows, @TRAN_Cum_Outflows, @descrpcion, @custodio, @fecha_tran, @fecha_vencimiento from gestor_transac**-------------------------                     

SELECT TOP 1 @shaba = gestor_transac.shabal , 
    @Coste_LOC_BAL = gestor_transac.Coste_LOC_BAL,
    @Coste_CAR_BAL = gestor_transac.Coste_CAR_BA,
    @TRAN_Cum_inflows = gestor_transac.TRAN_Cum_inflows,
    @TRAN_Cum_Outflows = gestor_transac.TRAN_Cum_Outflows,
    @descrpcion = gestor_transac.descrpcion,
    @custodio = gestor_transac.custodio,
    @fecha_tran = gestor_transac.fecha_tran,
    @fecha_vencimiento = gestor_transac.fecha_vencimiento
FROM gestor_transac 
WHERE CONVERT(date,gestor_transac.fecha_tran) <= CONVERT(date,@fecha_trade) 
AND gestor_transac.uid_producto= @uid_producto 
AND id_cartera= @Arg_ID_cartera
ORDER BY gestor_transac.fecha_tran DESC
       
------------------------------------**UPDATE**-------------------------         

UPDATE g SET cantidad = @shaba, 
    coste_div_loc = @Coste_LOC_BAL,
    coste_div_car = Coste_CAR_BAL,
    POS_cum_Inflows = @TRAN_Cum_inflows,
    POS_cum_Outflows = @TRAN_Cum_Outflows,
    Descripcion = @descrpcion,
    Custodio = @custodio,
    Fecha_compra = @fecha_tran,
    Fecha_vencimiento = @fecha_vencimiento
FROM  gestor_val_pos  g
WHERE id_cartera = @Arg_ID_cartera AND uid_producto= @Arg_UID_pr;

答案 1 :(得分:1)

您可以通过简单的联合更新来做到这一点:

fig, ((ax1, ax2), (ax3, ax4), (ax5, ax6)) = plt.subplots(nrows=3, ncols=2)

进一步说明:

  • UPDATE p SET cantidad = t.shabal , coste_div_loc = t.Coste_LOC_BAL , coste_div_car = t.Coste_CAR_BAL , POS_cum_Inflows = t.TRAN_Cum_inflows , POS_cum_Outflows = t.TRAN_Cum_Outflows , Descripcion = t.descrpcion , Custodio = t.custodio , Fecha_compra = t.fecha_tran , Fecha_vencimiento = t.fecha_vencimiento FROM gestor_val_pos AS p LEFT JOIN ( select top 1 t.shabal, t.Coste_LOC_BAL, t.Coste_CAR_BAL, t.TRAN_Cum_inflows, t.TRAN_Cum_Outflows, t.descrpcion, t.custodio, t.fecha_tran t.fecha_vencimiento from gestor_transac AS t where CONVERT(date, t.fecha_tran) <= CONVERT(date, p.fecha_trade) and t.uid_producto = p.uid_producto and id_cartera = @Arg_ID_cartera order by t.fecha_tran desc ) g where id_cartera = @Arg_ID_cartera and uid_producto = @Arg_UID_pr; 不会正确命中索引。而是使用 CONVERT(date, t.fecha_tran) <= CONVERT(date, p.fecha_trade)CONVERT(date, t.fecha_tran) <= p.fecha_trade 之类的内容,具体取决于您要点击的索引。
  • 我使用了 t.fecha_tran <= CONVERT(date, p.fecha_trade),您可以使用 LEFT JOIN 来代替
  • 根据基数(命中的行的百分比),使用行编号重写此方法可能或多或少有效率
  • 请注意别名 INNER JOINt 的使用,它们使读取和编写 SQL 变得更加容易
  • 始终指定所有列的表