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