SQL 中 XML 粉碎的替代方案
Posted
技术标签:
【中文标题】SQL 中 XML 粉碎的替代方案【英文标题】:Alternatives to XML shredding in SQL 【发布时间】:2014-04-10 04:56:35 【问题描述】:我尝试使用 XQuery .nodes
将 XML 分解为临时表,如下所示。但是,我遇到了性能问题。撕碎要花很多时间。请给我一个关于替代方案的想法。
我的要求是将批量记录传递给存储过程并解析这些记录并根据记录值进行一些操作。
CREATE TABLE #DW_TEMP_TABLE_SAVE(
[USER_ID] [NVARCHAR](30),
[USER_NAME] [NVARCHAR](255)
)
insert into #DW_TEMP_TABLE_SAVE
select
A.B.value('(USER_ID)[1]', 'nvarchar(30)' ) [USER_ID],
A.B.value('(USER_NAME)[1]', 'nvarchar(30)' ) [USER_NAME]
from
@l_n_XMLDoc.nodes('//ROW') as A(B)
【问题讨论】:
查看 XML 索引和架构集合。基本上,SQL Server 中的 XML 粉碎有一种非常慢的方式,直到您找到一种方法将数据放在可以索引的地方,甚至最好放在作为特定 schemacollection 类型的 XML 列上。他们一起可以进行持续数天的操作,例如不超过 30 秒(这就是我发生的事情)。在这里查看一个很好的例子:***.com/questions/61233/… 尽量避免使用//Row
的 XPath 表达式 - 这不对性能有好处!使用您的 XPath更具体!
@Kahn 在 SQL Server 2012 SP1 中使用 XML 索引,尤其是选择性 XML 索引可能是一件好事,但前提是您的数据存储在表中。这里的来源是一个XML变量@l_n_XMLDoc
。
感谢您的 cmets。让 XPath 更具体对我来说有些不同。
@MikaelEriksson:你是对的,在这种情况下,如果需要将变量更改为表格,至少是暂时的,最好知道这些选项是打开的。我有一个类似的场景,最初大量的 XML 数据存储在一个变量中,并且必须找到一种方法来提高性能。在这种情况下,解决方案确实是将其放入表中,以便对其进行索引并使其使用正确的 schemacollection。 :)
【参考方案1】:
在您的 values 子句中指定 text()
节点。
insert into #DW_TEMP_TABLE_SAVE
select A.B.value('(USER_ID/text())[1]', 'nvarchar(30)' ) [USER_ID],
A.B.value('(USER_NAME/text())[1]', 'nvarchar(30)' ) [USER_NAME]
from @l_n_XMLDoc.nodes('/USER_DETAILS/RECORDSET/ROW') as A(B)
不使用text()
将创建一个查询计划,该计划尝试将指定节点的值与其所有子节点连接起来,我猜你不希望在这种情况下这样做。如果您不使用 text()
,则查询的连接部分由 UDX 运算符完成,最好不要将它包含在您的计划中。
要尝试的另一件事是OPENXML。在某些情况下(大型 xml 文档),我发现 OPENXML 执行得更快。
declare @idoc int
exec sp_xml_preparedocument @idoc out, @l_n_XMLDoc
insert into #DW_TEMP_TABLE_SAVE
select USER_ID, USER_NAME
from openxml(@idoc, '/USER_DETAILS/RECORDSET/ROW', 2)
with (USER_ID nvarchar(30), USER_NAME nvarchar(30))
exec sp_xml_removedocument @idoc
【讨论】:
感谢您的回答。指定 text() 为我带来了一些改进。 它不是一些改进,它是巨大的。它适用于“在 XPATH 中更具体”和“价值条款中的文本()节点”。我想将您的答案设为 ACCEPTED ONE。为此,请编辑您的答案以使用 @l_n_XMLDoc.nodes('//RECORDSET/ROW')。 问题的示例 XML:以上是关于SQL 中 XML 粉碎的替代方案的主要内容,如果未能解决你的问题,请参考以下文章