SQL Delete语句执行时间太长

时间:2018-01-01 15:13:59

标签: sql sql-server sql-delete query-performance

我有以下SQL删除语句。这应该删除大约20000条记录,执行时间超过12分钟。在这里,我使用行号语句根据某些条件获取重复项。 任何想法修改脚本以更好地执行它。提前谢谢。

[{"positionint":1.0,"clicks":1138.0,"impressions":4768.0,"ctr":0.2386744966,"clickCtr10p":1251.8,"clickCtr50p":1707.0,"clickCtr100p":2276.0},{"positionint":2.0,"clicks":3160.0,"impressions":49899.0,"ctr":0.0633279224,"clickCtr10p":3476.0,"clickCtr50p":4740.0,"clickCtr100p":6320.0},{"positionint":3.0,"clicks":1255.0,"impressions":50020.0,"ctr":0.025089964,"clickCtr10p":1380.5,"clickCtr50p":1882.5,"clickCtr100p":2510.0},{"positionint":4.0,"clicks":363.0,"impressions":39077.0,"ctr":0.0092893518,"clickCtr10p":399.3,"clickCtr50p":544.5,"clickCtr100p":726.0},{"positionint":5.0,"clicks":216.0,"impressions":18419.0,"ctr":0.011727021,"clickCtr10p":237.6,"clickCtr50p":324.0,"clickCtr100p":432.0},{"positionint":6.0,"clicks":307.0,"impressions":15447.0,"ctr":0.0198744093,"clickCtr10p":337.7,"clickCtr50p":460.5,"clickCtr100p":614.0},{"positionint":7.0,"clicks":248.0,"impressions":24709.0,"ctr":0.0100368287,"clickCtr10p":272.8,"clickCtr50p":372.0,"clickCtr100p":496.0},{"positionint":8.0,"clicks":236.0,"impressions":26853.0,"ctr":0.0087885897,"clickCtr10p":259.6,"clickCtr50p":354.0,"clickCtr100p":472.0},{"positionint":9.0,"clicks":139.0,"impressions":26577.0,"ctr":0.0052300862,"clickCtr10p":152.9,"clickCtr50p":208.5,"clickCtr100p":278.0},{"positionint":10.0,"clicks":23.0,"impressions":2046.0,"ctr":0.0112414467,"clickCtr10p":25.3,"clickCtr50p":34.5,"clickCtr100p":46.0},{"positionint":null,"clicks":7085.0,"impressions":257815.0,"ctr":null,"clickCtr10p":7793.5,"clickCtr50p":10627.5,"clickCtr100p":14170.0},{"positionint":null,"clicks":null,"impressions":null,"ctr":null,"clickCtr10p":1417.0,"clickCtr50p":7085.0,"clickCtr100p":14170.0}]

3 个答案:

答案 0 :(得分:1)

使用#temp表而不是表变量并创建以下索引

CREATE NONCLUSTERED INDEX NIX_temp
  ON #temptable (Date, IsDeleted, RO, PP)
  include (id, Dep, NrInvoiceLine, OfficeId, pol, pod, PreCarr, WarehouseId, DestinationPrecarr, DestinationWarehouseId, PortTerminalId, Product, description, ScaleCalcuationId, scalefrom, scaleto, CurrencyCode, Base, ShippingLineID, ContainerId, AgentId);

并尝试像这样更改查询

;WITH cte
     AS (SELECT Row_number()
                  OVER(
                    partition BY Dep, NrInvoiceLine, OfficeId, pol, pod, PreCarr, WarehouseId, DestinationPrecarr, DestinationWarehouseId, PortTerminalId, Product, Isnull(description, ''), ScaleCalcuationId, Isnull(scalefrom, 0), Isnull(scaleto, 0), CurrencyCode, Base, ShippingLineID, ContainerId, AgentId
                    ORDER BY type) Record,
                a.id
         FROM   #temptable a
         WHERE  Date >= '2078-12-31 00:00:00'
                AND Date < Dateadd(dd, 1, '2078-12-31 00:00:00')
                AND IsDeleted = 0
                AND ( RO = 1
                       OR RO = 2 )
                AND ( PP = 0
                       OR PP = 2 ))
DELETE FROM cte
WHERE  Record > 1 

答案 1 :(得分:0)

在我看来,你需要将查询分解为更小的块。这是你正在进行的高分区。

是否有更简单的方法来实现您想要的输出?您是否需要从此表中删除,或者您是否可以创建另一个只包含您想要的行,然后删除包含您不感兴趣的行的表?结果相同的方法不同。

值得注意的是,创建表格的效果大多优于插入和删除行。

编辑:我可以看到你正试图减轻已经返回的副本。 99%的时间这是清理错误编码的一种方法。找出引入副本的原因,并采取正确修复数据集所需的相关步骤。

答案 2 :(得分:0)

可能导致性能不佳的主要原因是因为表变量不能获得准确的行估计值,除非您使用OPTION (RECOMPILE)。因此,您可能正在根据估计表变量包含的行数远少于实际行数来计划。

此处也没有子查询。

你应该发现这个执行得更快。

WITH CTE
     AS (SELECT ROW_NUMBER() OVER(partition BY Dep, NrInvoiceLine, OfficeId, pol, pod, PreCarr, WarehouseId, DestinationPrecarr, DestinationWarehouseId, PortTerminalId, Product, isnull(description, ''), ScaleCalcuationId, isnull(scalefrom, 0), isnull(scaleto, 0), CurrencyCode, Base, ShippingLineID, ContainerId, AgentId ORDER BY type) Record,
                a.id
         FROM   @TempTable a
         WHERE  cast(Date AS SMALLDATETIME) = '2078-12-31 00:00:00'
                AND IsDeleted = 0
                AND ( RO IN ( 1, 2 ) )
                AND ( PP IN ( 0, 2 ) ))
DELETE FROM CTE
WHERE  Record > 1 
OPTION (RECOMPILE)