2017-05-08 144 views
3

我有下面的代码...提高性能SP

UPDATE Sales 
    SET MappingOrderID = CAST ([dbo].[fRemoveNonNumericCharacters] (ltrim(rtrim(ActualOrderNumber))) AS INT) 
    FROM Sales 
    where isnumeric(ActualOrderNumber) = 1 
    and ActualOrderNumber not like '%.%' 
    and len(ActualOrderNumber) < 10 
    and MappingOrderID is null 
    and ActualOrderNumber is not null 
    and ltrim(rtrim(ActualOrderNumber)) in (select ltrim(rtrim(OrderID)) from dbo.Orders) 

参与的栏目有:

销售: MappingOrderId INT ActualOrderNumber NVARCHAR(10)

从订单: 的OrderId INT

这是遗留代码,我是DBA,我不知道他/她为什么使用T轮圈这么多...脚本需要9分钟跑,理想必须频繁地运行......

我也是在执行计划中得到这样的:

  • CONVERT_IMPLICIT(VARCHAR(12),[数据集市] [DBO]。[指令]。[订单ID],0)

  • CONVERT_IMPLICIT(VARCHAR(20),[Datamart的]。[DBO]。[销售]。[ActualOrderNumber],0)

  • 表达式中的类型转换(CONVERT_IMPLICIT(varchar(20),[DataMart]。[dbo]。[Sales]。[ActualOrderNumber],0) )可能会影响查询计划选择中的“CardinalityEstimate”,表达式中的类型转换(CONVERT_IMPLICIT(varchar(12),[Datamart]。[dbo]。[Orders]。[OrderID],0))可能会影响查询计划中的“CardinalityEstimate”选择

对于我感觉到...

它更新MappingOrderId(INT)铸造ActualOrderNumber(VARCHAR)...这将只有ActualOrderNumber在订单存在更新...

我尝试了一些修改;但VARCHAR ActualOrderNumber有一个像3545427103值,如果我尝试删除像什么:

and len(ActualOrderNumber) < 10 

这将打破...

我的总体目标是使这一进程的最有效的可能;在源头上修复数据是唯一真正的解决方案?

我实施了很多建议,并且下降到了一分钟。谢谢!但我不明白的是:

之前,用丑陋的代码我有: enter image description here

现在我有更多的读取...它需要几秒钟跑......这怎么可能? enter image description here

+0

LIKE也非常昂贵。如果你知道逻辑,肯定有办法改进这个查询。这是在订单号字段中检查美元价值吗?这可以更改为CONTAINS。怎么了只返回长度小于10的订单号呢? –

+1

如果您有机会,请将包含已清理的订单号的列添加到两个表中,然后对其进行填充并将其编入索引。总共花费的时间可能不会少于九分钟。在将最后的'IN'更改为'exists'时,您可能会看到一些优势,但请检查更改之间的查询计划。 –

+0

哦,你也有一个UDF可能会放慢速度。查询计划应该给你一些想法。要计算CardinalityEstimate是否真的受到影响,请比较实际和估计计划,并查看行数是否在相同的附近 –

回答

1
UPDATE Sales 
SET MappingOrderID = CAST (ltrim(rtrim(ActualOrderNumber)) AS INT) 
FROM Sales S 
inner join dbo.Orders O on ltrim(rtrim(O.OrderID))=ltrim(rtrim(s.ActualOrderNumber)) 
where isnumeric(ActualOrderNumber) = 1 
and ActualOrderNumber not like '%.%' 
and len(ActualOrderNumber) < 10 
and MappingOrderID is null 

变化

1.删除功能 “fRemoveNonNumericCharacters”

  • 当你正在检查在where子句中,没有必要使用此功能ISNUMERIC。

2.加入销售和订单表

  • 如果你将使用Orders表where子句中为你所提到的,那么对于销售表的每一行,完整的订单表将被渲染。
  • 为了减少这个过程,我添加了连接。

3.删除当你正在检查在where子句中,没有必要使用这个条件ISNUMERIC ActualOrderNumeric不为空

  • 。因为为null,则isnumeric将返回0.
+0

也许可以增加 “并且包含(ActualOrderNumber, '')” 哪应该比NOT LIKE子句更高效。希望这些列被索引。 –