简体   繁体   English

删除速度很慢

[英]Delete very slow

I need to delete only the first appear of a record. 我只需要删除一条记录的第一次出现。 This have a PK ( preld_item, IDENTITY ). 这有一个PK( preld_item, IDENTITY )。

This is the very slow DELETE.. 这是非常慢的DELETE ..

DELETE pd
FROM   preliquidaciones_deta pd
WHERE  pd.preld_item IN (SELECT MAX(p.preld_item)
                         FROM   preliquidaciones_deta p
                         WHERE  p.id_preliquidacion = '216'
                         GROUP  BY p.id_sds_linea_equipo,
                                   p.id_concepto
                         HAVING COUNT(p.id_sds_linea_equipo) > 1) 

Thanks 谢谢

EDIT: 编辑:

  • The table has more than 5 million rows 该表有超过500万行
  • id_preliquidacion has a clustered index (pk) id_preliquidacion具有聚集索引(pk)

EDIT 2: @vulkanino i think in you answer and i modify the delete... 编辑2:@vulkanino我想在你的答案,我修改删除...

DECLARE @loPreldItem INT
DECLARE curItems CURSOR FOR (select max(p.preld_item)
    from preliquidaciones_deta p 
    where p.id_preliquidacion = '216' 
    group by p.id_sds_linea_equipo, p.id_concepto
    having count(p.id_sds_linea_equipo) > 1)

OPEN curItems
FETCH NEXT FROM curItems INTO @loPreldItem
WHILE @@FETCH_STATUS = 0
BEGIN
    DELETE FROM preliquidaciones_deta WHERE preld_item = @loPreldItem
    FETCH NEXT FROM curItems INTO @loPreldItem
END
CLOSE curItems
DEALLOCATE curItems

This works best but continue slow 效果最佳,但持续缓慢

EDIT 3: The execution plan of the first delete 编辑3:第一次删除的执行计划

delete from preliquidaciones_deta where preld_item in (  select max(preld_item)  from preliquidaciones_deta   where id_preliquidacion = '216'  group by id_sds_linea_equipo, id_concepto, preld_nse, preld_linea  having count(id_preliquidacion) > 1)
  |--Assert(WHERE:(CASE WHEN NOT [Expr1018] IS NULL THEN (0) ELSE CASE WHEN NOT [Expr1019] IS NULL THEN (1) ELSE NULL END END))
       |--Nested Loops(Left Semi Join, OUTER REFERENCES:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_item]), DEFINE:([Expr1019] = [PROBE VALUE]))
            |--Nested Loops(Left Semi Join, OUTER REFERENCES:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_item]), DEFINE:([Expr1018] = [PROBE VALUE]))
            |    |--Clustered Index Delete(OBJECT:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[PK_preliquidaciones_deta]), OBJECT:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[IX_id_sds]), OBJECT:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[IX_id_sds_linea_equipo]))
            |    |    |--Top(ROWCOUNT est 0)
            |    |         |--Sort(DISTINCT ORDER BY:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_item] ASC))
            |    |              |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1007]) OPTIMIZED)
            |    |                   |--Filter(WHERE:([Expr1006]>(1)))
            |    |                   |    |--Compute Scalar(DEFINE:([Expr1006]=CONVERT_IMPLICIT(int,[Expr1023],0)))
            |    |                   |         |--Stream Aggregate(GROUP BY:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[id_sds_linea_equipo], [data_dealernet_lucom].[dbo].[preliquidaciones_deta].[id_concepto], [data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_nse], [data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_linea]) DEFINE:([Expr1023]=Count(*), [Expr1007]=MAX([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_item])))
            |    |                   |              |--Sort(ORDER BY:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[id_sds_linea_equipo] ASC, [data_dealernet_lucom].[dbo].[preliquidaciones_deta].[id_concepto] ASC, [data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_nse] ASC, [data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_linea] ASC))
            |    |                   |                   |--Clustered Index Scan(OBJECT:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[PK_preliquidaciones_deta]), WHERE:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[id_preliquidacion]='216'))
            |    |                   |--Clustered Index Seek(OBJECT:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[PK_preliquidaciones_deta]), SEEK:([data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_item]=[Expr1007]) ORDERED FORWARD)
            |    |--Clustered Index Scan(OBJECT:([data_dealernet_lucom].[dbo].[liquidaciones_deta].[PK_liquidaciones_deta]), WHERE:([data_dealernet_lucom].[dbo].[liquidaciones_deta].[preld_item]=[data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_item]))
            |--Table Scan(OBJECT:([data_dealernet_lucom].[dbo].[liquidaciones_diferidas]), WHERE:([data_dealernet_lucom].[dbo].[liquidaciones_diferidas].[preld_item]=[data_dealernet_lucom].[dbo].[preliquidaciones_deta].[preld_item]))

You could try this alternative (as you state there won't be more than 2 rows per id_sds_linea_equipo, id_concepto this has the same semantics as your original query) 您可以尝试这种选择(因为您声明每个id_sds_linea_equipo, id_concepto有2行id_sds_linea_equipo, id_concepto的语义与原始查询的语义相同)

WITH T
     AS (SELECT *,
                RN = ROW_NUMBER() OVER 
                                 (PARTITION BY id_sds_linea_equipo, id_concepto
                                      ORDER BY preld_item)

         FROM   preliquidaciones_deta
         WHERE  id_preliquidacion = '216')
DELETE FROM T
WHERE RN > 1  

Change IN with = since the subquery returns only on row. =更改IN ,因为子查询仅在行上返回。 (to begin with). (首先)。

不知道它是否适用于您的情况(由于HAVING子句),但是ORDER BY p.preld_item DESC LIMIT 1可能比最大聚合快得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM