提高将大型 xml 文件 (~300 MB) 转换为 SQL Server 中的关系表的性能

1 performance xml sql-server xquery

所以这就是我到目前为止所拥有的:

--Read xml content into a XML data type variable
DECLARE @FileData XML
SELECT @FileData = CONVERT(XML, BulkColumn)
FROM OPENROWSET(BULK '\\file_path\test.xml', SINGLE_BLOB) AS x
--Read from the XML variable to create Entity-Attribute-Value table
SELECT N1.Id.value('@Id', 'varchar(50)') as Id
    , N1.Id.value('@Name', 'varchar(100)') as Name
    , N2.AttributeLongName.value('@AttributeName', 'varchar(100)') as AttributeName
    , N3.AttributeValue.value('.', 'varchar(MAX)') as AttributeValue
FROM @FileData.nodes('/Data/Entities/Entity') as N1(Id) ---1st lvl Node contains the Entity
cross apply Id.nodes('Attributes/Attribute') as N2(AttributeName) --2nd lvl Node contains AttributeName
cross apply AttributeName.nodes('Values/Value') as N3(AttributeValue) --3rd lvl Node contains AttributeValue
Run Code Online (Sandbox Code Playgroud)

此代码在针对 8 MB XML 文件(~15 秒)运行时表现良好。但是,当我尝试针对具有相同结构的 300 MB XML 文件运行它时,它需要几个小时。

这是否意味着 XQuery nodes() 方法不能线性扩展或扩展得最差?

有没有其他方法可以提高性能?

wBo*_*Bob 5

我又看了一遍,可以重现您的问题。尝试添加OPTION ( MAXDOP 1 )到您的查询中。在我的带有 300MB 文件的测试设备中,它在 1 分 42 秒内运行。在我杀死它之前,未提示的版本以 100% CPU 运行了 30 分钟。

你也可以看看OPENXML。人们经常说使用大型 XML 文件会更快,在这种情况下似乎是这样。但是,您应该了解已知问题OPENXML(例如,可以占用缓冲池的 1/8,是老式的 COM .dll,您必须调用sp_xml_removedocument等)。一旦你研究了 的利弊OPENXML,你可以尝试这样的事情:

DECLARE @FileData XML

SELECT @FileData = BulkColumn
FROM OPENROWSET(BULK 'd:\temp\temp.xml', SINGLE_BLOB) AS x

DECLARE @hDoc int

EXEC sp_xml_preparedocument @hDoc OUTPUT, @FileData 

SELECT *
INTO #tmp
FROM OPENXML( @hDoc, '/Data/Entities/Entity/Attributes/Attribute/Values/Value', 1 ) 
WITH
    (
    Id VARCHAR(50) '../../../../@Id',
    Name VARCHAR(100) '../../../../@Name',
    AttributeName VARCHAR(100)  '../../@AttributeName',
    AttributeValue VARCHAR(MAX) '.'
    )

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

老实说,由于这些问题,这些天我尽量避免使用它;当您刚刚砍掉缓冲池的 1/8 时,一个查询速度更快有什么意义?

最后,最快和最可扩展的方法(恕我直言)是 SSIS。对于与我的装备中的上述方法相同的文件,此版本在大约 10 秒内运行。

SSIS XML 导入方法

创建一个包,添加一个数据流任务,添加一个 XML 源,然后添加每个表。我创建了一个与你的结构相同的 300MB 文件,它在大约 10 秒内加载,例如

在此处输入图片说明

显然,您需要额外的时间来查询您导入的表,但我认为这是一种更安全的方法。您甚至可以使用多个包来扩展它。如果您需要有关包裹的更多帮助,请回帖。