Sql-Server

提高在 SQL Server 中將大型 xml 文件 (~300 MB) 轉換為關係表的性能

  • October 23, 2018

所以這就是我到目前為止所擁有的:

--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

此程式碼在針對 8 MB XML 文件(約 15 秒)執行時表現良好。但是,當我嘗試針對相同結構的 300 MB XML 文件執行它時,需要花費數小時。

這是否意味著 XQuery nodes() 方法不能線性擴展或擴展最差?

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

我又看了一遍,可以重現您的問題。嘗試添加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

老實說,由於這些問題,這些天我試圖避免它;當您剛剛減少 1/8 的緩衝池時,一個查詢更快有什麼意義?

最後,最快和最可擴展的方法(恕我直言)是 SSIS。對於與我的裝備中的上述方法相同的文件,此版本在大約 10 秒內執行。

SSIS XML 導入方法

創建一個包,添加一個數據流任務,添加一個 XML 源,然後添加每個表。我創建了一個與你的結構相同的 300MB 文件,它在大約 10 秒內載入,例如

在此處輸入圖像描述

顯然,您需要額外的時間來查詢已導入的表,但我認為這是一種更安全的方法。你甚至可以用多個包來擴展它。如果您在包裹方面需要更多幫助,請回帖。

引用自:https://dba.stackexchange.com/questions/91091