sql >> データベース >  >> RDS >> Sqlserver

XMLデータをSQLServerデータベース列に細断処理す​​るための最良の方法

    非常によく似た問題を抱えているときにこの質問に出くわしましたが、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をサポートしていません。つまり、他のスキーマを参照するスキーマがある場合は、これらすべてを1つのスキーマにコピーして、それを追加する必要があります。

    また、エラーが発生します:

    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. MySQLパフォーマンス–構成ファイルからの5つのパラメーター

    2. DROPデータベースのアクセス許可なしでコマンドラインからすべてのMySQLテーブルを削除するにはどうすればよいですか?

    3. データベーススキーマをどのようにバージョン管理しますか?

    4. SQLServerのUNIX_TIMESTAMP