【问题标题】:performance of isnull vs select case statementisnull vs select case语句的性能
【发布时间】:2014-06-26 15:52:36
【问题描述】:

什么更快?

update c
set 
c.createdon=q.CreatedOn 
,c.createdby=case when q.createdby is not null then q.createdby end
,c.modifiedon=q.modifiedon 
,c.modifiedby=case when q.ModifiedBy is not null then q.ModifiedBy end
from crm_annotationbase c
join IncidentWorknote q
on c.annotationid=q.annotationid

或者这个:

update c
set 
c.createdon=q.CreatedOn 
,c.createdby=isnull(q.createdby,c.createdby) 
,c.modifiedon=q.modifiedon 
,c.modifiedby=isnull(q.modifiedby,c.modifiedby)
from crm_annotationbase c
join IncidentWorknote q
on c.annotationid=q.annotationid

我的第一个查询已经运行了 24 小时。我正在根据暂存数据更新 CRM 2013 表。

我想知道我是否选择了最有效的解决方案?

【问题讨论】:

  • 如果您想优化 24 小时查询以显着加快运行速度,那么我最不想看到的就是空值检查。这实际上只是选择此查询的任意元素并将其归咎于性能问题。
  • 本文详细介绍了 COALESCE 和 ISNULL 之间的性能。 COALESCE 基本上是幕后的 CASE。 sqlmag.com/t-sql/coalesce-vs-isnull
  • 同意上面的说法,为什么不通过 where q.modifiedon >= GetDate() -1 来加快速度
  • 你一直在更新所有的记录,你只需要更新那些已经改变的。我假设你每天都在运行它。您可以相对轻松地限制要更新的记录。
  • @MikeMiller 非常感谢你。但我不知道如何判断记录是否已更改。我只需要运行一次这个过程。

标签: sql sql-server tsql sql-server-2012 dynamics-crm-2013


【解决方案1】:

好的.. 我不得不四处寻找这个脚本。通过阅读 cmets,您正在尝试更新它是一个非常大的表。加快此更新的最佳方法是将其分成批次。花费这么长时间的原因是由于系统的事务性质......如果出现故障,整个事务(您的整个更新)将被回滚。这需要额外的时间。如果您不需要这种事务性的全有或全无,请尝试这样的事情(如下)。我们必须更新数以亿计的记录,并且我们能够通过批量更新将其加快 HOURS。

根据您的数据调整它可以让您更快。

DECLARE @Update INT
                DECLARE @Batch INT

                -- Total number of records in database
                SELECT @Update = (
                    SELECT COUNT(id)
                    FROM [table] WITH (NOLOCK) -- be CAREFUL with this
                    WHERE [' + @fName + '] IS NOT NULL) --optional

                SELECT @Batch = 4000 --Batch update amount

                WHILE (@Update > 0)
                    BEGIN

                    UPDATE TOP(@Batch) c
                    set 
                    c.createdon=q.CreatedOn 
                    ,c.createdby=case when q.createdby is not null then q.createdby end
                    ,c.modifiedon=q.modifiedon 
                    ,c.modifiedby=case when q.ModifiedBy is not null then q.ModifiedBy end
                    from crm_annotationbase c
                    join IncidentWorknote q
                    on c.annotationid=q.annotationid

                    SELECT @Update = @Update - @Batch; -- Reduce for next set

                    WAITFOR DELAY '000:00:00.400'; -- Allows for waiting transactions to process optional
                    END;

【讨论】:

  • 另外,如果 annotationId 是主键,这会更快。您可以添加一个 where 语句,例如“其中 annotationId 在 @minBatch 和 @maxBatch 之间的位置”或类似的东西。 :)
  • 是的.. 这对我们来说是最有效的。您可以尝试以更高的批次运行它。但是在生产运行之前确保逻辑是正确的(显然)。 TOP 对我们有用,因为我使用 WHERE 语句限制更新,这样当四千条记录更新时,它们不再在 TOP 组中(因为不满足条件)。
【解决方案2】:

你做错了有两个原因:

  1. 对 Dynamics CRM 数据库的直接更新非常不受支持,并且可能会导致您的 CRM 实例出现多个问题(您需要使用 CRM Web 服务来更新数据)
  2. CreatedOnCreatedByModifiedOnModifiedBy 是系统字段,它们总是被填充,它们从不包含空值。 (特别是CreatedOnCreatedBy是在创建记录时指定的,之后就不能修改了,ModifiedOnModifiedBy每次更新记录都会更新)

按照微软的建议: http://msdn.microsoft.com/en-us/library/gg328350.aspx#Unsupported

不支持的自定义项

使用 SQL 命令或 Microsoft Dynamics CRM SDK 中描述的技术以外的任何技术更改 Microsoft Dynamics CRM 数据库中的数据(记录)。

【讨论】:

  • 1.请告诉我一个消息来源,说这些特定字段手动更新是危险的。我已经就此与 CRM MVP 进行过交谈,他说这很好。
  • 2.正确,但我正在临时数据库中检查空值,而不是在 crm 中
  • 您是否正在更新 CRM 数据库?我不敢相信 CRM MVP 说可以直接更新 CRM 数据库。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 1970-01-01
  • 2013-03-23
  • 2014-12-05
  • 2017-06-13
  • 2015-02-27
相关资源
最近更新 更多