簡體   English   中英

加快將XML文件插入SQL Server表的速度

[英]Speeding up inserting XML file into SQL Server table

我正在使用以下腳本使用Powershell將大型XML文件(3.5Gb)插入本地SQL Server表'files_index中,因為該文件超出了SQL的2 GB限制。

表結構如下,然后是PowerShell腳本。 該文件包含大約5000000行,但是要花費很長的時間才能插入,盡管這樣做行之有效,但我正在尋找可以加快速度的任何方法(目前大約需要15分鍾)。

關於加快處理速度的任何建議,我都嘗試過增加批處理大小,但這似乎並沒有太大的區別,我不久前在stackoverflow上獲得了此powershell腳本,但我只是想簡化流程。 感謝您的協助或建議。

CREATE TABLE [dbo].[files_index]
(
    [Product_ID] [int] NOT NULL,
    [path] [varchar](100) NULL,
    [Updated] [varchar](50) NULL,
    [Quality] [varchar](50) NULL,
    [Supplier_id] [int] NULL,
    [Prod_ID] [varchar](100) NULL,
    [Catid] [int] NULL,
    [On_Market] [int] NULL,
    [Model_Name] [varchar](250) NULL,
    [Product_View] [varchar](250) NULL,
    [HighPic] [varchar](250) NULL,
    [HighPicSize] [int] NULL,
    [HighPicWidth] [int] NULL,
    [HighPicHeight] [int] NULL,
    [Date_Added] [varchar](150) NULL,

    CONSTRAINT [PK_files_index] 
        PRIMARY KEY CLUSTERED ([Product_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]

PowerShell腳本:

Set-ExecutionPolicy Unrestricted -scope LocalMachine

[String]$global:connectionString = "Data Source=Apps2\Apps2;Initial 
Catalog=DTEDATA;Integrated Security=SSPI";
[System.Data.DataTable]$global:dt = New-Object System.Data.DataTable;
[System.Xml.XmlTextReader]$global:xmlReader = New-Object 
System.Xml.XmlTextReader("C:\Scripts\icecat\files.index.xml");
[Int32]$global:batchSize = 100000;

Function Add-FileRow() {
    $newRow = $dt.NewRow();
    $null = $dt.Rows.Add($newRow);

    $newRow["Product_ID"] = $global:xmlReader.GetAttribute("Product_ID");
    $newRow["path"] = $global:xmlReader.GetAttribute("path");
    $newRow["Updated"] = $global:xmlReader.GetAttribute("Updated");
    $newRow["Quality"] = $global:xmlReader.GetAttribute("Quality");
    $newRow["Supplier_id"] = $global:xmlReader.GetAttribute("Supplier_id");
    $newRow["Prod_ID"] = $global:xmlReader.GetAttribute("Prod_ID");
    $newRow["Catid"] = $global:xmlReader.GetAttribute("Catid");
    $newRow["On_Market"] = $global:xmlReader.GetAttribute("On_Market");
    $newRow["Model_Name"] = $global:xmlReader.GetAttribute("Model_Name");
    $newRow["Product_View"] = $global:xmlReader.GetAttribute("Product_View");
    $newRow["HighPic"] = $global:xmlReader.GetAttribute("HighPic");
    $newRow["HighPicSize"] = $global:xmlReader.GetAttribute("HighPicSize");
    $newRow["HighPicWidth"] = $global:xmlReader.GetAttribute("HighPicWidth");
    $newRow["HighPicHeight"] = $global:xmlReader.GetAttribute("HighPicHeight");
    $newRow["Date_Added"] = $global:xmlReader.GetAttribute("Date_Added");
}

# init data table schema
$da = New-Object System.Data.SqlClient.SqlDataAdapter("SELECT * FROM 
files_index WHERE 0 = 1", $global:connectionString);
$null = $da.Fill($global:dt);

$bcp = New-Object System.Data.SqlClient.SqlBulkCopy($global:connectionString);
$bcp.DestinationTableName = "dbo.files_index";

$recordCount = 0;

while($xmlReader.Read() -eq $true)
{

    if(($xmlReader.NodeType -eq [System.Xml.XmlNodeType]::Element) -and 
($xmlReader.Name -eq "file"))
    {
        Add-FileRow -xmlReader $xmlReader;
        $recordCount += 1;
        if(($recordCount % $global:batchSize) -eq 0) 
        {
            $bcp.WriteToServer($dt);
            $dt.Rows.Clear();
            Write-Host "$recordCount file elements processed so far";
        }
    }

}

if($dt.Rows.Count -gt 0)
{
    $bcp.WriteToServer($dt);
}

$bcp.Close();
$xmlReader.Close();

Write-Host "$recordCount file elements imported ";

catch
{
    throw;
}

這足夠接近,可以標記為以下內容的重復...

在SQL Server中導入和解析大型XML文件(“正常”方法相當慢時)

接受的答案:

好。 我在XML數據列上創建了XML索引。 (現在只是一個主要的)。 現在,花費約4:30分鍾的查詢現在花費約9秒! 似乎一個存儲有適當XML索引的XML並使用xml.nodes()函數解析數據的表是可行的解決方案。

提高將大型xml文件(〜300 MB)轉換為SQL Server中的關系表的性能

接受的答案:

我對此進行了另一番研究,可以重現您的問題。 嘗試將OPTION(MAXDOP 1)添加到查詢中。 在我的具有300MB文件的測試台中,此命令在1分鍾42秒內運行。 在我殺死它之前,無提示版本在100%CPU上運行了30分鍾。 您也可以看看OPENXML。 人們經常說,使用大型XML文件,速度更快,而且在這種情況下似乎確實如此。 但是,您應該了解OPENXML的已知問題(例如,可能占用1/8的緩沖池,是老式的COM .dll,必須調用sp_xml_removedocument等)。 研究了OPENXML的優缺點之后,您可以嘗試執行以下操作:

DECLARE @FileData XML

SELECT @FileData = BulkColumn
FROM OPENROWSET(BULK 'd:\temp\temp.xml', SINGLE_BLOB) AS x

DECLARE @hDoc int

EXEC sp_xml_preparedocument @hDoc OUTPUT, @FileData 

SELECT *
INTO #tmp
FROM OPENXML( @hDoc, '/Data/Entities/Entity/Attributes/Attribute/Values/Value', 1 ) 
WITH
    (
    Id VARCHAR(50) '../../../../@Id',
    Name VARCHAR(100) '../../../../@Name',
    AttributeName VARCHAR(100)  '../../@AttributeName',
    AttributeValue VARCHAR(MAX) '.'
    )

EXEC sp_xml_removedocument @hDoc

老實說,由於這些問題,我最近盡量避免使用它。 當您僅緩沖了緩沖池的1/8時,一個查詢執行得更快有什么意義? 最后,最快,最具擴展性的方法(IMHO)是SSIS。 與我的裝備中的上述方法相同的文件,此版本運行約10秒鍾。 SSIS XML導入方法創建一個包,添加一個Data Flow任務,添加一個XML Source,然后添加每個表。 我創建了一個結構與您相同的300MB文件,並在大約10秒鍾內加載了該文件,例如

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM