Je suis tombé sur cette question alors que j'avais un problème très similaire, j'avais exécuté une requête traitant un fichier XML de 7,5 Mo (environ 10 000 nœuds) pendant environ 3,5 à 4 heures avant d'abandonner finalement.
Cependant, après un peu plus de recherche, j'ai découvert qu'après avoir tapé le XML à l'aide d'un schéma et créé un index XML (j'aurais inséré en bloc dans une table), la même requête s'est terminée en ~ 0,04 ms.
Comment est-ce pour une amélioration des performances !
Code pour créer un schéma :
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
Code pour créer la table avec une colonne XML typée :
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]
Code pour créer l'index
CREATE PRIMARY XML INDEX PXML_Data
ON [dbo].[XmlFiles] (Data)
Il y a cependant quelques éléments à garder à l'esprit. L'implémentation de Schema par SQL Server ne prend pas en charge xsd:include. Cela signifie que si vous avez un schéma qui fait référence à un autre schéma, vous devrez tous les copier dans un seul schéma et l'ajouter.
J'obtiendrais également une erreur :
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) ?'.
si j'essayais de naviguer au-dessus du nœud que j'avais sélectionné avec la fonction nodes. Par exemple
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)
J'ai découvert que la meilleure façon de gérer cela était d'utiliser OUTER APPLY pour effectuer en fait une "jointure externe" sur le 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)
J'espère que cela aidera quelqu'un, car c'est à peu près ma journée.