我正在使用以下脚本使用powershell将大型XML文件(3.5Gb)插入本地SQL Server表'files_index
,因为该文件超过了SQL的2 GB限制。
表结构如下,然后是PowerShell脚本。该文件包含约500万行,但要花很长时间插入,而此方法行之有效,并且确实正在寻找任何方法来加速它(目前大约需要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;
}
答案 0 :(得分:0)
距离足够近,可以标记为以下内容的重复...
Importing and parsing a large XML file in SQL Server (when “normal” methods are rather slow)
可接受的答案:
好。我在XML数据列上创建了XML索引。 (只是一个主要的 目前)。现在,花费约4:30分钟的查询现在花费约9秒! 似乎该表存储具有正确XML索引的XML和 用xml.nodes()函数解析数据是可行的 解决方案。
Improve performance of converting a large xml file (~300 MB) to relational table in SQL Server
可接受的答案:
我对此有另一种看法,可以重现您的问题。尝试添加 选项(MAXDOP 1)进行查询。在我的测试装备中,有300MB的文件 这花了1分钟42秒。未提示的版本运行了30分钟 在我杀死它之前以100%的CPU运行。您也可以看看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。该版本与 以上方法在我的钻机上。 SSIS XML导入方法创建一个包,添加 一个数据流任务,添加一个XML Source,然后添加每个表。我创建了一个 300MB档案,与您的档案结构相同,大约10颗档案 秒,例如