Tình cờ gặp câu hỏi này trong khi gặp một vấn đề tương tự, tôi đã chạy một truy vấn xử lý tệp XML 7,5MB (~ khoảng 10.000 nút) trong khoảng 3,5 ~ 4 giờ trước khi cuối cùng bỏ cuộc.
Tuy nhiên, sau khi nghiên cứu thêm một chút, tôi nhận thấy rằng khi nhập XML bằng lược đồ và tạo Chỉ mục XML (tôi muốn chèn hàng loạt vào bảng) thì cùng một truy vấn đã hoàn thành trong ~ 0,04ms.
Làm thế nào để cải thiện hiệu suất!
Mã để tạo một lược đồ:
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
Mã để tạo bảng với một cột XML đã nhập:
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]
Mã tạo Chỉ mục
CREATE PRIMARY XML INDEX PXML_Data
ON [dbo].[XmlFiles] (Data)
Tuy nhiên, có một số điều cần ghi nhớ. Việc triển khai Lược đồ của SQL Server không hỗ trợ xsd:include. Điều này có nghĩa là nếu bạn có một lược đồ tham chiếu đến lược đồ khác, bạn sẽ phải sao chép tất cả những thứ này vào một giản đồ duy nhất và thêm vào đó.
Ngoài ra, tôi sẽ gặp lỗi:
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) ?'.
nếu tôi cố gắng điều hướng phía trên nút mà tôi đã chọn với chức năng nút. Ví dụ:
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)
Nhận thấy rằng cách tốt nhất để xử lý vấn đề này là sử dụng ỨNG DỤNG NGOÀI TRỜI để thực hiện "kết nối bên ngoài" trên 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)
Hy vọng rằng điều đó sẽ giúp ích cho ai đó giống như ngày hôm nay của tôi.