Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Cách tốt nhất để chia nhỏ dữ liệu XML thành các cột cơ sở dữ liệu SQL Server

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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Làm cách nào để thay đổi cơ sở dữ liệu mặc định của tôi trong SQL Server mà không cần sử dụng MS SQL Server Management Studio?

  2. Lý do nên nâng cấp lên SQL Server 2017

  3. Tăng trưởng kích thước cơ sở dữ liệu SQL Server bằng lịch sử sao lưu

  4. Có thể truy cập cơ sở dữ liệu .mdf mà không có SQL Server không?

  5. Kết nối với SQL Server 2012 bằng sqlalchemy và pyodbc