Menemukan pertanyaan ini ketika memiliki masalah yang sangat mirip, saya telah menjalankan kueri yang memproses file XML 7,5MB (~kira-kira 10.000 node) selama sekitar 3,5~4 jam sebelum akhirnya menyerah.
Namun, setelah sedikit penelitian lebih lanjut, saya menemukan bahwa setelah mengetik XML menggunakan skema dan membuat Indeks XML (saya akan memasukkan secara massal ke dalam tabel) kueri yang sama diselesaikan dalam ~ 0,04 ms.
Bagaimana dengan peningkatan kinerja!
Kode untuk membuat skema:
IF EXISTS ( SELECT * FROM sys.xml_schema_collections where [name] = 'MyXmlSchema')
DROP XML SCHEMA COLLECTION [MyXmlSchema]
GO
DECLARE @MySchema XML
SET @MySchema =
(
SELECT * FROM OPENROWSET
(
BULK 'C:\Path\To\Schema\MySchema.xsd', SINGLE_CLOB
) AS xmlData
)
CREATE XML SCHEMA COLLECTION [MyXmlSchema] AS @MySchema
GO
Kode untuk membuat tabel dengan kolom XML yang diketik:
CREATE TABLE [dbo].[XmlFiles] (
[Id] [uniqueidentifier] NOT NULL,
-- Data from CV element
[Data] xml(CONTENT dbo.[MyXmlSchema]) NOT NULL,
CONSTRAINT [PK_XmlFiles] PRIMARY KEY NONCLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Kode untuk membuat Indeks
CREATE PRIMARY XML INDEX PXML_Data
ON [dbo].[XmlFiles] (Data)
Ada beberapa hal yang perlu diingat. Implementasi Skema SQL Server tidak mendukung xsd:include. Artinya, jika Anda memiliki skema yang mereferensikan skema lain, Anda harus menyalin semua ini ke dalam satu skema dan menambahkannya.
Saya juga akan mendapatkan kesalahan:
XQuery [dbo.XmlFiles.Data.value()]: Cannot implicitly atomize or apply 'fn:data()' to complex content elements, found type 'xs:anyType' within inferred type 'element({http://www.mynamespace.fake/schemas}:SequenceNumber,xs:anyType) ?'.
jika saya mencoba menavigasi di atas node yang saya pilih dengan fungsi node. Mis.
SELECT
,C.value('CVElementId[1]', 'INT') AS [CVElementId]
,C.value('../SequenceNumber[1]', 'INT') AS [Level]
FROM
[dbo].[XmlFiles]
CROSS APPLY
[Data].nodes('/CVSet/Level/CVElement') AS T(C)
Menemukan bahwa cara terbaik untuk menangani ini adalah dengan menggunakan OUTER APPLY untuk melakukan "outer join" pada XML.
SELECT
,C.value('CVElementId[1]', 'INT') AS [CVElementId]
,B.value('SequenceNumber[1]', 'INT') AS [Level]
FROM
[dbo].[XmlFiles]
CROSS APPLY
[Data].nodes('/CVSet/Level') AS T(B)
OUTER APPLY
B.nodes ('CVElement') AS S(C)
Semoga itu bisa membantu seseorang karena itu adalah hari saya.