Наткнулся на этот вопрос, хотя у меня была очень похожая проблема, я выполнял запрос, обрабатывающий XML-файл объемом 7,5 МБ (~ около 10 000 узлов), в течение 3,5-4 часов, прежде чем окончательно сдаться.
Однако после небольшого исследования я обнаружил, что после ввода XML-кода с использованием схемы и создания XML-индекса (я бы вставил его в таблицу) тот же запрос был выполнен за ~ 0,04 мс.
Как это для улучшения производительности!
Код для создания схемы:
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
Код для создания таблицы с типизированным столбцом XML:
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]
Код для создания индекса
CREATE PRIMARY XML INDEX PXML_Data
ON [dbo].[XmlFiles] (Data)
Есть несколько вещей, которые следует иметь в виду, хотя. Реализация схемы в SQL Server не поддерживает xsd: include. Это означает, что если у вас есть схема, которая ссылается на другую схему, вам придется скопировать все это в одну схему и добавить ее.
Также я получил бы ошибку:
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) ?'.
если я попытался перейти выше узла, выбранного с помощью функции узлов. Э.Г.
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)
Обнаружено, что лучший способ справиться с этим - использовать OUTER APPLY для выполнения "внешнего соединения" в 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)
Надеюсь, это кому-нибудь поможет, ведь это был мой день.