Office中国论坛/Access中国论坛

标题: 巧用链接服务器同步数据 [打印本页]

作者: roych    时间: 2018-12-14 12:23
标题: 巧用链接服务器同步数据
有时候我们可能需要某个数据库的个别表,但同步数据往往会遇到一些问题。例如,由于权限问题无法发布订阅远程数据库。这时候链接服务器几乎成为不二选择了。但全量更新通常也会遇到一些问题,例如,当数据超过1000万行的时候。
最初我的思路是每天只更新不一样的数据。当时打算通过主键来匹配,新增的就更新,原表不存在的则删除。后来发现,还存在更改的很难判断。主键不变,如果每个字段去检查是否变更,相当繁琐。

所以打算不再同步数据表,而改为将所需基础数据追加到本地。如此一来,将不必更新多个表,而改为若干个字段就足矣。

在实际操作过程中,一开始是打算按查询的思路来完成,把所需的表进行整合,一次性把所需数据提取出来,发现需要运行很久。于是决定拆开多个查询,单表追加基础数据后,再逐步更新,应该会好些。
经测试,查询数据是比较快的,但追加到本地表则很慢,即便只有几万行。因此开始怀疑可能是运行脚本时需要调用大量资源,便思考是否可以考虑临时表来处理。于是就有了以下脚本:
  1. CREATE PROCEDURE [dbo].[A9_Sametime](@startDate date = null) as
  2. if @startDate is null
  3. set @startDate=GETDATE()

  4. declare
  5. --长日期
  6. @startDateTime datetime,
  7. @firstDayDateTime datetime,

  8. @endDateTime datetime,
  9. @sql1 varchar(8000),
  10. @sql2 varchar(1000),
  11. @sql3 varchar(1000)


  12. set @startDateTime=DATEADD(day,-1,@startDate)
  13. set @firstDayDateTime=DATEADD(day,1-day(@startDate),@startDate)
  14. set @endDateTime=DATEADD(MILLISECOND,-3,convert(datetime,@startdate))



  15. --追加前一天数据
  16. set @sql1 = 'select * into ##temp from openquery(A9Server, ''select CustomerID 客服ID,SalesStaff 工号,max(StartTime) 最近接通日期,'
  17. +' CONVERT(VARCHAR(8),DATEADD(ss,sum(BillableSeconds),''''1900-01-01 00:00:00''''),108) as 通话时长,'
  18. +' count(SalesStaff) 通话次数, sum(case when BillableSeconds>=1 then 1 else 0 end) 接通次数,'
  19. +' Destination 外呼号码 from [A9SERVER].[S60623].[dbo].[bmdcallcenterrecord] '
  20. +' where StartTime between '''''+convert(varchar(23),@startDateTime,21)+''''' and '''''
  21. +convert(varchar(23),@endDateTime,21)+''''' group by CustomerID,SalesStaff,Destination'')'


  22. --更新订单号信息
  23. set @sql2 = 'select * into ##temp from openquery(A9Server,''select a.CustomerID,a.ID,a.LastFollowDate,'
  24. +' a.LastFollowContent,cs.CommunicateStatus from [A9SERVER].[S60623].[dbo].[bdCustomerAllocate] a,'
  25. +' [A9SERVER].[S60623].[dbo].[mdcommunicatestatus] cs where len(a.LastCommunicateStatus)>0  '
  26. +' and LastFollowDate between '''''+convert(varchar(23),@startDateTime,21)+''''' and '''''
  27. +convert(varchar(23),@endDateTime,21)+''''' and a.LastCommunicateStatus=convert(varchar(50),cs.ID)'')'


  28. --更新提醒信息
  29. set @sql3 = 'select * into ##temp from openquery(A9Server,'
  30. +' ''select u.UserName,d.DepartName,u.WorkNo from [A9SERVER].[S60623].[dbo].[frmuser] u,'
  31. +' [A9SERVER].[S60623].[dbo].[mdDepartment] d where u.DepartmentID=d.id'')'


  32. BEGIN
  33. --set nocount on
  34. --set nocount off
  35. exec(@sql1)

  36. insert into tblWidth(客户ID,工号,最近接通日期, 通话时长,通话次数,接通次数,外呼号码)
  37. select * from ##temp

  38. if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..##temp') and type='U')
  39. drop table ##temp
  40. --
  41. exec(@sql2)

  42. update tblWidth  set 分配ID=s.ID,最后沟通时间=s.LastFollowDate,沟通结果=s.LastFollowContent,
  43. 沟通状态=s.CommunicateStatus from ##temp s where
  44. s.CustomerID=tblWidth.客户ID and tblWidth.分配ID is null

  45. if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..##temp') and type='U')
  46. drop table ##temp

  47. exec(@sql3)

  48. update tblWidth  set 客服=UserName,部门=DepartName from ##temp s
  49. where s.WorkNo=工号 and 客服 is null

  50. if exists (select * from tempdb.dbo.sysobjects where id = object_id(N'tempdb..##temp') and type='U')
  51. drop table ##temp
  52. END
复制代码
值得注意的是,双井号(##)才可以多次使用。用单井号(#)则运行完第一个语句后,临时表将消失(即第二个语句将出现错误)。拼接SQL语句比较麻烦,但考虑到需要按日期来执行语句,而且涉及到链接服务器(openquery),那也是必不可免的事情了。在拼接过程中,大家需要注意单引号的使用。



作者: roych    时间: 2018-12-14 18:26
注意:第三句应改为:
set @startDate=DATEADD(day,-1,GETDATE())
估计输入参数"2018-12-14"之类会被默认为文本。因此,需要用一个dateadd转为日期吧。
作者: zpy2    时间: 2019-3-29 16:16
否可以考虑临时表来处理。
为什么用临时表会快点?感觉插入了二次,应该慢才对。
作者: roych    时间: 2019-3-29 16:47
zpy2 发表于 2019-3-29 16:16
否可以考虑临时表来处理。
为什么用临时表会快点?感觉插入了二次,应该慢才对。

直接处理的话,相当于调用CPU来计算。而临时表会先把数据调入缓存,只要缓存足够大,通常比直接处理要快的。这就类似于读取内存数据和读取硬盘数据的意思。
作者: zpy2    时间: 2019-3-30 17:52
roych 发表于 2019-3-29 16:47
直接处理的话,相当于调用CPU来计算。而临时表会先把数据调入缓存,只要缓存足够大,通常比直接处理要快 ...

哦,难不是还有这样子啊,长知识了。




欢迎光临 Office中国论坛/Access中国论坛 (http://www.office-cn.net/) Powered by Discuz! X3.3