XML 解析缓慢

jdm*_*310 8 xml sql-server temporary-tables

我目前正在尝试调整一个有点问题的存储过程,我注意到与运行它相关的大部分成本来自将一些 XML 解析为临时表。这是有问题的SQL:

CREATE TABLE #ChangeSet 
(
    RemarkTypeID TINYINT NOT NULL PRIMARY KEY,
    RemarkText VARCHAR(2500) NOT NULL,
    ListingID INT NOT NULL
)
INSERT INTO #ChangeSet
    (RemarkTypeID, 
    RemarkText,
    ListingID)
SELECT
    T.c.value('@RemarkTypeID[1]','tinyint') AS RemarkTypeID,
    T.c.value('@RemarkText[1]','varchar(2500)') AS RemarkText,
    @ListingID
FROM @RemarksXml.nodes('/Remarks[1]/Remark') AS T(c)
Run Code Online (Sandbox Code Playgroud)

此外,您对正在解析的 XML 的结构有了一些了解:

  <Remarks>
    <Remark xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" RemarkID="211767" DateTimeCreated="1991-11-19T10:43:50" DateTimeModified="1992-01-01T10:43:50" RemarkTypeID="8" RemarkText="aaaWasher,Dryer,Refriger,Microwav" />
    <Remark xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" RemarkID="211768" DateTimeCreated="1991-11-19T10:43:50" DateTimeModified="1992-01-01T10:43:50" RemarkTypeID="3" RemarkText="aaaell Maintained 3Bd 1.5Ba Semi-Detached Home In Cambridge Gardens. Garage W As Converted Into A Nice Family Room The Outside Is Maintence Free. Includes All Appliances,Security System,Storage Shed,Ceiling Fans And New Carpet.This Home Is Very Well Pricded. Seller Will Consider Fha Or Va Along With Conventional Finacing. This Is A Great Buy." />
 </Remarks>
Run Code Online (Sandbox Code Playgroud)

我可以做些什么来提高解析这些 XML 节点和设置这个临时表的性能?

Dan*_*her 5

提高 xml 解析性能主要有两件事:

  • 使 xml 变量/列类型化,这意味着在其上声明一个 xsd 架构。这将强制验证 xml,这本身会花费一点时间,但解析速度会提高。
  • 对 xml 列建立索引(不适用于 xml 变量)。您可以根据您的要求,通过多种不同的方式对xml 列建立索引。对于 xml blob 中更复杂的查询和查找,这可能会带来出色的性能提升。
  • 如果您的查询是一个更大查询的一部分,我似乎记得 xml 操作不会并行化,因此您可能会明智地分解一个大型查询,并在与其余工作分开的单独查询中进行 xml 解析。

  • 不过,我认为三件事。:-) (4认同)

wBo*_*Bob 5

你可以试试OPENXML。现在我通常不推荐OPENXML它,因为它有许多众所周知的内存问题(基本上它可以占用缓冲池的 1/8,具体取决于 XML 的大小)(!!TODO 添加链接)。不管传说如何,对于较大的 XML 片段来说它更快,因此在开发/测试环境中值得一试,如果您知道内存问题,并且获得了性能,则由您决定最需要哪个。像这样的东西:

DECLARE @handle INT

EXEC sp_xml_preparedocument @handle OUTPUT, @RemarksXml

INSERT INTO #ChangeSet
SELECT RemarkTypeID, RemarkText, @ListingID
FROM OPENXML( @handle, '/Remarks[1]/Remark', 1 ) 
WITH ( 
    RemarkTypeID    TINYINT,
    RemarkText      VARCHAR(2500)
    )

EXEC sp_xml_removedocument @handle
Run Code Online (Sandbox Code Playgroud)

记得总是打电话sp_xml_removedocument。我猜你真正的 XML 大得多,你能告诉我们Remark它将有多少元素以及大小是多少 KB / MB。稍后我将回到该帖子并设置一个测试设备以根据您的统计数据比较性能。

更新:根据您的示例脚本,您的 XML 最多只能有 256 个Remark元素,最大长度为 2500。创建了一些示例 XML 以满足这些标准并对其进行了测试,这两种技术之间的性能几乎没有在亚秒内完成。在这种情况下,我会选择 XML 数据类型和方法。你能提供要求的其他信息吗?

  • SQL Server 使用 MSXML 和 DOM 来处理您通过 sp_xml_preparedocument 加载的文档。它将 MSXML 可用于 DOM 处理的虚拟内存限制为机器物理内存的八分之一或 500MB,**以较小者为准**。 (3认同)