Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Най-добрият начин за раздробяване на XML данни в колони на база данни на SQL Server

Попаднах на този въпрос, докато имах много подобен проблем, изпълнявах заявка, обработваща 7,5 MB XML файл (~приблизително 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)

Надявам се това да помогне на някого, тъй като това беше моят ден.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Различно представяне на UUID в Java Hibernate и SQL Server

  2. Има ли рискове за сигурността, свързани с наблюдението в облака на Spotlight?

  3. Как да проверя дали съществува база данни в SQL Server?

  4. Използвайте OBJECTPROPERTY(), за да разберете дали даден обект е ограничение CHECK в SQL Server

  5. Промяна на приоритета на акаунт в пощенски профил на база данни (SSMS)