【发布时间】:2021-07-31 08:00:00
【问题描述】:
我发布了这个问题
INSERT Statement Expensive Queries on Activity Monitor
正如您将看到的那样,XML 结构具有不同的层次。
我创建了不同的表
Organisation = organisation_id (PRIMARY_KEY)
Contacts = organisation_id (FOREIGN_KEY)
Roles = organisation_id (FOREIGN_KEY)
Rels = organisation_id (FOREIGN_KEY)
Succs = organisation_id (FOREIGN_KEY)
我想要的是生成organisation_id 并以级联方式对每个表进行插入。目前,300k 的过程需要将近 2 个小时。我有 3 种方法
-
将 XML 转换为列表对象并以 JSON 文本形式批量发送(1000)并发送到使用 OPENJSON 的存储过程
-
将 XML 转换为列表对象并按批次发送 (1000) 并将批次保存为 JSON 文件,SQL Server 可以读取该文件并在存储过程中传递文件路径,然后使用 OPENROWSET 和 OPENJSON 打开 JSON 文件
-
将 XML 的路径发送到存储过程,然后使用 OPENROWSET 和 OPENXML。
所有进程 (1-3) 将数据插入到 FLAT 临时表中,然后迭代每一行以为每个表调用不同的 INSERT 存储过程。方法 #3 似乎因 300k 错误而失败,但适用于 4 条记录。
另一个问题是,如果我使用物理表会比使用临时表快得多吗?
-------更新------- 正如链接上所解释的,我正在做while循环。有人建议/评论对每个表进行批量插入。问题是,例如,我只能在知道组织 ID 的情况下执行此操作
select
organisation_id = IDENTITY( bigint ) -- IF I CAN GENERATE THE ACTUAL ORGANISATION ID
,name = Col.value('.','nvarchar(20)')
,contact_type = c.value('(./@type)[1]','nvarchar(50)')
,contact_value= c.value('(./@value)[1]','nvarchar(50)')
into
#temporganisations
from
@xml.nodes('ns1:OrgRefData/Organisations/Organisation') as Orgs(Col)
outer apply Orgs.Col.nodes('Contacts/Contact') as Cs(c)
然后当我进行批量插入时
insert into contacts
(
organisation_id,type,value
)
select
torg.organisation_id -- if this is the actual id then perfect
,torg.type
,torg.value
from #temporg torg
【问题讨论】:
-
您的问题究竟是什么?你似乎在解释你在做什么,并且它有效?
-
目前,300k 是在将近 2 小时内完成的。我试图找到一种方法来加快它。目前,我正在执行一个 while 循环以从具有 300k 行的临时表中获取数据,并调用 5 个存储过程在每个表上插入。我希望不是在临时表上有一个身份,而是我可以为 organization_id 保留 id,这样我就可以使用它来进行选择并在每个表上进行批量插入,而不是 while 循环。我将更新帖子以尝试解释我的意思
-
不确定我的观察是否正确。当我批量处理时(方法 #2),while 循环的处理速度比我使用 OPENXML(方法 #3)时快一点(每秒大约 200 条记录),因为表有 300k 它可能需要很长时间时间(大约每秒 2-3 条记录)。
-
你如何放弃所有这些并使用 C# 中的
SqlBulkCopy或bcp命令行来批量插入全部内容。它可能会快一个数量级。如果您正在向表中插入,为什么要将其转换为 XML 或 JSON 并再次返回 -
@Charlieface。我只为组织信息完成了 SqlBulkCopy,而且速度很快。唯一的麻烦是我需要将组织链接到的其他表。就像我可以创建一个批量联系人,但我需要组织 ID。我认为在 api 中循环并一次调用一个存储过程比批量处理更昂贵。这就是为什么我需要转换为 JSON。请注意,原始数据是 XML。
标签: sql-server openxml openrowset open-json