2017-04-07 8 views
0

내가 SQL에 1백60기가바이트 CSV 파일을로드하려고하고 내가 Github에서 가져온 PowerShell 스크립트를 사용하고 내가오류 : 입력 배열이 테이블 PowerShell을 열 수보다 긴

IException calling "Add" with "1" argument(s): "Input array is longer than the number of columns in this table." 
At C:\b.ps1:54 char:26 
+ [void]$datatable.Rows.Add <<<< ($line.Split($delimiter)) 
    + CategoryInfo   : NotSpecified: (:) [], MethodInvocationException 
    + FullyQualifiedErrorId : DotNetMethodException 

그래서이 오류를 얻을 작은 3 줄 csv와 동일한 코드를 검사하고 모든 열이 일치하고 첫 번째 행에 헤더가 있고 왜이 오류가 발생하는지 확실하지 않은 여분의 구분 기호가 없습니다.

코드는 160 기가 바이트의 입력 파일로 작업

<# 8-faster-runspaces.ps1 #> 
# Set CSV attributes 
$csv = "M:\d\s.txt" 
$delimiter = "`t" 

# Set connstring 
$connstring = "Data Source=.;Integrated Security=true;Initial Catalog=PresentationOptimized;PACKET SIZE=32767;" 

# Set batchsize to 2000 
$batchsize = 2000 

# Create the datatable 
$datatable = New-Object System.Data.DataTable 

# Add generic columns 
$columns = (Get-Content $csv -First 1).Split($delimiter) 
foreach ($column in $columns) { 
[void]$datatable.Columns.Add() 
} 

# Setup runspace pool and the scriptblock that runs inside each runspace 
$pool = [RunspaceFactory]::CreateRunspacePool(1,5) 
$pool.ApartmentState = "MTA" 
$pool.Open() 
$runspaces = @() 

# Setup scriptblock. This is the workhorse. Think of it as a function. 
$scriptblock = { 
    Param (
[string]$connstring, 
[object]$dtbatch, 
[int]$batchsize 
    ) 

$bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($connstring,"TableLock") 
$bulkcopy.DestinationTableName = "abc" 
$bulkcopy.BatchSize = $batchsize 
$bulkcopy.WriteToServer($dtbatch) 
$bulkcopy.Close() 
$dtbatch.Clear() 
$bulkcopy.Dispose() 
$dtbatch.Dispose() 
} 

# Start timer 
$time = [System.Diagnostics.Stopwatch]::StartNew() 

# Open the text file from disk and process. 
$reader = New-Object System.IO.StreamReader($csv) 

Write-Output "Starting insert.." 
while ((($line = $reader.ReadLine()) -ne $null)) 
{ 
[void]$datatable.Rows.Add($line.Split($delimiter)) 

if ($datatable.rows.count % $batchsize -eq 0) 
{ 
    $runspace = [PowerShell]::Create() 
    [void]$runspace.AddScript($scriptblock) 
    [void]$runspace.AddArgument($connstring) 
    [void]$runspace.AddArgument($datatable) # <-- Send datatable 
    [void]$runspace.AddArgument($batchsize) 
    $runspace.RunspacePool = $pool 
    $runspaces += [PSCustomObject]@{ Pipe = $runspace; Status = $runspace.BeginInvoke() } 

    # Overwrite object with a shell of itself 
    $datatable = $datatable.Clone() # <-- Create new datatable object 
} 
} 

# Close the file 
$reader.Close() 

# Wait for runspaces to complete 
while ($runspaces.Status.IsCompleted -notcontains $true) {} 

# End timer 
$secs = $time.Elapsed.TotalSeconds 

# Cleanup runspaces 
foreach ($runspace in $runspaces) { 
[void]$runspace.Pipe.EndInvoke($runspace.Status) # EndInvoke method retrieves the results of the asynchronous call 
$runspace.Pipe.Dispose() 
} 

# Cleanup runspace pool 
$pool.Close() 
$pool.Dispose() 

# Cleanup SQL Connections 
[System.Data.SqlClient.SqlConnection]::ClearAllPools() 

# Done! Format output then display 
$totalrows = 1000000 
$rs = "{0:N0}" -f [int]($totalrows/$secs) 
$rm = "{0:N0}" -f [int]($totalrows/$secs * 60) 
$mill = "{0:N0}" -f $totalrows 

Write-Output "$mill rows imported in $([math]::round($secs,2)) seconds ($rs rows/sec and $rm rows/min)" 
+0

이 경우 일반적으로이 오류는 일부 줄에 예기치 않은 포함 된 구분 기호 ... 탭이 있음을 나타냅니다. 조금 더러운 입력 데이터 일뿐입니다. 행을 읽은 다음 탭을 빈 문자열로 바꾸고 원래의 크기와 축소 된 크기를 비교하여 열이있는 행보다 많은 행을 볼 수 있습니다. 네 개의 열이있는 경우 행이 세 자로 줄어들 것으로 예상됩니다. –

+0

@Laughing Vergil 답장을 보내 주셔서 감사합니다. 쉼표로 구분 된 파일에 대해 동일한 결과를 얻었으므로 같은 오류가 발생합니다. – Zack

+0

일부 데이터의 줄 종결자가 문제가 발생할 수 있습니다 - Windows 스타일의 텍스트 파일 중간에 UNIX 스타일의 줄 바꿈이있는 경우 하나의 데이터 검색 작업에서 두 ​​행으로 끝납니다. 삽입 된 줄 바꿈 또는 CR/LF 쌍은 처리를 망칠 수도 있습니다. –

답변

1

는 통증이있을 예정이다 이하입니다. 어떤 종류의 편집기에도 실제로로드 할 수 없으며 적어도 심각한 자동화 없이는 그러한 데이터를 분석 할 수 없습니다.

의견에 따르면 데이터에 품질 문제가있는 것으로 보입니다. 기분 나쁜 데이터를 찾으려면 이진 검색을 시도해보십시오. 이 방법은 데이터를 빠르게 축소합니다. 마찬가지로,

1) Split the file in about two equal chunks. 
2) Try and load first chunk. 
3) If successful, process the second chunk. If not, see 6). 
4) Try and load second chunk. 
5) If successful, the files are valid, but you got another a data quality issue. Start looking into other causes. If not, see 6). 
6) If either load failed, start from the beginning and use the failed file as the input file. 
7) Repeat until you narrow down the offending row(s). 

또 다른 방법은 SSIS와 같은 ETL 도구를 사용하는 것입니다. 잘못된 행을 오류 로그로 리디렉션하도록 패키지를 구성하여 올바르게 작동하지 않는 데이터를 확인하십시오.

+0

SSIS 옵션에 대해 1을 더합니다. – Bruce