Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Json 在活动监视器上插入语句查询_Json_Sql Server_Insert_Open Json - Fatal编程技术网

Json 在活动监视器上插入语句查询

Json 在活动监视器上插入语句查询,json,sql-server,insert,open-json,Json,Sql Server,Insert,Open Json,我有一个大约300k的对象列表。我通过网络API批量发送这个。由于这个对象是一个多级对象,我决定以1000个一批的方式发送这些项目,并将其转换为JSON字符串。目前,我看到每秒插入大约50条记录,据我估计,完成这些记录大约需要1个多小时 在我的SQL Server中,我有一个接受JSON字符串并使用OPENJSON的存储过程。数据被插入到一个诱人的文件中,然后我重复使用它,但如图所示,我不确定是否有更好的方法 While (Select Count(*) From #temporganisati

我有一个大约300k的对象列表。我通过网络API批量发送这个。由于这个对象是一个多级对象,我决定以1000个一批的方式发送这些项目,并将其转换为JSON字符串。目前,我看到每秒插入大约50条记录,据我估计,完成这些记录大约需要1个多小时

在我的SQL Server中,我有一个接受JSON字符串并使用OPENJSON的存储过程。数据被插入到一个诱人的文件中,然后我重复使用它,但如图所示,我不确定是否有更好的方法

While (Select Count(*) From #temporganisations Where process_ind = 0) > 0
Begin
  select top 1
     @orgid=torg.orgid
  from
     #temporganisations torg
  where torg.process_ind=0
  exec AddOrganisation... retvalid out
  exec AddLocation...retvalid
  exec AddContact...retvalid
  etc
  .
  .
  .
  delete from #temporganisations        
    where orgid= @orgid
 
end
如图所示,此存储过程中调用了多个存储过程。每个存储过程在执行INSERT语句之前都有重复的检查。我正试图加快这个过程。完成这个过程真的需要很长时间。因此,我发现了活动监视器,并注意到如下所示的“最近昂贵的查询”显示了调用的INSERT语句

我只是想知道我是否可以做些什么来提高这些插件的性能,下面是其中一个插件的执行计划

我在某个地方读到,我可以直接插入,但存储过程将是巨大的,因为我需要添加重复的检查。我还读过关于使用变量表而不是临时表的文章,但我也读过一篇文章,说变量表是用于小数据集的。提前谢谢

下面是XML结构。如您所见,我需要将每个子节点链接到父节点(即组织)

<Organisations>
<Organisation orgRecordClass="R43">
  <Name>ORGANIZATION X</Name>
  <Date>
    <Type value="Operational" />
    <Start value="1991-04-01" />
    <End value="1994-03-31" />
  </Date>
  <OrgId root="5161f" assigningAuthorityName="H51" extension="R34" />
  <Status value="Inactive" />
  <LastChangeDate value="2013-05-08" />
  <GeoLoc>
    <Location>
      <AddrLn1>458 HOMER ROAD</AddrLn1>
      <Town>LONDON</Town>
      <PostCode>E1 8PL</PostCode>
      <Country>ENGLAND</Country>
      <UPRN>21521</UPRN>
    </Location>
  </GeoLoc>
  <Contacts>
    <Contact type="tel" value=" 233344" />
    <Contact type="fax" value=" 233355" />
  </Contacts>
  <Roles>
    <Role id="R12" uniqueRoleId="1" primaryRole="true">
      <Date>
        <Type value="Operational" />
        <Start value="1991-04-01" />
        <End value="1994-03-31" />
      </Date>

    </Role>
  </Roles>
  <Rels>
    <Rel id="RE6" uniqueRelId="58005">
      <Date>
        <Type value="Operational" />
        <Start value="1991-04-01" />
        <End value="1994-03-31" />
      </Date>
      <Status value="Inactive" />

    </Rel>
  </Rels>

  <Succs>
    <Succ uniqueSuccId="12">
      <Date>
        <Type value="Legal" />
        <Start value="1993-04-01" />
      </Date>
      <Type>Successor</Type>
      <Target>
        <OrgId root="5161f" assigningAuthorityName="H51" extension="R561" />
        <PrimaryRoleId id="R12" uniqueRoleId="37607" />
      </Target>
    </Succ>       
    <Succ uniqueSuccId="12">
      <Date>
        <Type value="Legal" />
        <Start value="1993-04-01" />
      </Date>
      <Type>Successor</Type>
      <Target>
        <OrgId root="5161f" assigningAuthorityName="H51" extension="R561" />
        <PrimaryRoleId id="R12" uniqueRoleId="37607" />
      </Target>
    </Succ>
  </Succs>
</Organisation>

第一件事是遵循SQL Server中逐行运行流程的基本最佳实践。在这里,这意味着使用一个真正的游标,而不是像游标一样奇怪的循环,并将整个循环包装在一个事务中

begin transaction

declare c cursor local for 
   select * from #temporganisations
open c

fetch next from c into @orgid, @name, ...
while @@fetch_status = 0
begin
  
  exec AddLocation...
  exec AddContact...
  etc
  .
  .
  .
  fetch next from c into @orgid, @name, ...
end

commit transaction
如果没有事务,则必须在每次插入后物理刷新事务日志

第二件事是将其转换为面向批处理的流程。您可以重写每个存储过程以接受多个输入行TVP、JSON或XML,或者只对每个存储过程进行编码以从临时组织中读取。存储过程可以使用会话中声明的任何临时表,因此可以通过在调用进程之前插入临时表,将大容量数据传递到存储过程中

乙二醇


毫无疑问,最重要的是加快流程的方法,但这一切都取决于您调用的每个过程中发生了什么。目前,while循环逻辑应该检查是否存在任何行,而不是要求Sql Server在每次迭代中不必要地将它们全部计算出来……谢谢@Stu。每个商店的程序都没有什么特别的。它只是使用select获取id是否存在,如果不存在,则调用INSERT。我可以问一个更好的方法来检查是否存在任何行吗?这是一个更好的方法吗?从process\u ind=0的临时组织中选择1基本上是的-如果表中有很多行,即1000多行,那么process\u ind上的索引将有所帮助。使用exists Sql server将在遇到符合条件的行时立即停止,而不是每次计算所有行,这将影响行数是否很大。您应该重写此操作以批量执行:从表值参数或临时表插入可能最快感谢@davidbrowne,我已经添加了我正在处理的xml结构。正如您所看到的,子节点是链接的,这意味着我需要先获取组织id,然后再将其插入其他表。如果您要告诉某人在while循环上使用光标,至少要正确地执行基本操作:使用快进,或者使用try/catch进行适当的清理,或者使用@variable cursor自动解除定位本地游标具有批处理范围并且不需要清理。您是否认为临时表上的快进游标比常规动态游标快得多?
create or alter procedure AddLocation
as
begin
   insert into Location (Name, Address)
   select distinct Name, Address
   from #temporganisations
end