2017-12-04 10 views
0

私は開発者でもCSV専門家でもありません。私はこのコードを一緒に置くことができ、それは仕事をしています。 概要を簡単に紹介するため、CSVにネストされたJSONデータを処理する必要がありました。だから私はJSONを読んでいるので、それを別の列に分割して、CSVを保存しています。Powershell - ネストされたJSONでCSV処理を最適化する

さて、私の問題は、これが正常に動作しているが、私は今、1.5GB CSVファイルを処理する必要があると私は処理は2日かかるしたくないということです...

だからみんなができればそれが妥当な時間内に実行されるように、私は私のスクリプトを微調整に役立ち、私は非常に感謝される:)

$file = Get-Content -Path 'input.csv' | Select-Object -Skip 2 | ConvertFrom-Csv 
$file | Add-Member -MemberType NoteProperty -Name AdditionalInfo_StreamingEndpointName -value $null 
$file | Add-Member -MemberType NoteProperty -Name AdditionalInfo_Id -value $null 
$file | Add-Member -MemberType NoteProperty -Name AdditionalInfo_AppServicePlanUri -value $null 
$file | Add-Member -MemberType NoteProperty -Name AdditionalInfo_ImageType -value $null 
$file | Add-Member -MemberType NoteProperty -Name AdditionalInfo_ServiceType -value $null 
$file | Add-Member -MemberType NoteProperty -Name AdditionalInfo_VMName -value $null 
$file | Add-Member -MemberType NoteProperty -Name AdditionalInfo_UsageType -value $null 
$file | Add-Member -MemberType NoteProperty -Name AdditionalInfo_DatabaseAccount -value $null 
$file | Add-Member -MemberType NoteProperty -Name AdditionalInfo_CollectionRid -value $null 
$file | Add-Member -MemberType NoteProperty -Name AdditionalInfo_ResourceCategory -value $null 
$file | Add-Member -MemberType NoteProperty -Name Tags_displayName -value $null 
$file | Add-Member -MemberType NoteProperty -Name 'Tags_ACCESSED-VIA-INTERNET' -value $null 
$file | Add-Member -MemberType NoteProperty -Name 'Tags_APP-NAME' -value $null 
$file | Add-Member -MemberType NoteProperty -Name 'Tags_APP-TYPE' -value $null 
$file | Add-Member -MemberType NoteProperty -Name Tags_APPTYPE -value $null 
$file | Add-Member -MemberType NoteProperty -Name Tags_CHARGECODE -value $null 
$file | Add-Member -MemberType NoteProperty -Name Tags_COMMENTS -value $null 
$file | Add-Member -MemberType NoteProperty -Name Tags_COUNTRY -value $null 
$file | Add-Member -MemberType NoteProperty -Name 'Tags_EY-REGION' -value $null 
$file | Add-Member -MemberType NoteProperty -Name 'Tags_IT-ENV' -value $null 
$file | Add-Member -MemberType NoteProperty -Name Tags_OWNER -value $null 
$file | Add-Member -MemberType NoteProperty -Name 'Tags_OWNER-EMAIL' -value $null 
$file | Add-Member -MemberType NoteProperty -Name Tags_SERVICELINE -value $null 
$file | Add-Member -MemberType NoteProperty -Name 'Tags_SUB-TYPE' -value $null 
$file | Add-Member -MemberType NoteProperty -Name Tags_TECHCONTACTS -value $null 

$count=1 
ForEach ($line in $file) { 
Write-Output "Processing line: $count" 
$count++ 
try{ 
    if ($line.AdditionalInfo -ne $null -Or $line.Tags -ne $null){ 
     $line.AdditionalInfo_StreamingEndpointName = ($line.AdditionalInfo | ConvertFrom-JSON).StreamingEndpointName 
     $line.AdditionalInfo_Id = ($line.AdditionalInfo | ConvertFrom-JSON).Id 
     $line.AdditionalInfo_AppServicePlanUri = ($line.AdditionalInfo | ConvertFrom-JSON).AppServicePlanUri 
     $line.AdditionalInfo_ImageType = ($line.AdditionalInfo | ConvertFrom-JSON).ImageType 
     $line.AdditionalInfo_ServiceType = ($line.AdditionalInfo | ConvertFrom-JSON).ServiceType 
     $line.AdditionalInfo_VMName = ($line.AdditionalInfo | ConvertFrom-JSON).VMName 
     $line.AdditionalInfo_UsageType = ($line.AdditionalInfo | ConvertFrom-JSON).UsageType 
     $line.AdditionalInfo_DatabaseAccount = ($line.AdditionalInfo | ConvertFrom-JSON).DatabaseAccount 
     $line.AdditionalInfo_CollectionRid = ($line.AdditionalInfo | ConvertFrom-JSON).CollectionRid 
     $line.AdditionalInfo_ResourceCategory = ($line.AdditionalInfo | ConvertFrom-JSON).ResourceCategory 
     $line.Tags_displayName = ($line.Tags | ConvertFrom-JSON).displayName 
     $line.'Tags_ACCESSED-VIA-INTERNET' = ($line.Tags | ConvertFrom-JSON).'ACCESSED-VIA-INTERNET' 
     $line.'Tags_APP-NAME' = ($line.Tags | ConvertFrom-JSON).'APP-NAME' 
     $line.'Tags_APP-TYPE' = ($line.Tags | ConvertFrom-JSON).'APP-TYPE' 
     $line.Tags_APPTYPE = ($line.Tags | ConvertFrom-JSON).APPTYPE 
     $line.Tags_CHARGECODE = ($line.Tags | ConvertFrom-JSON).CHARGECODE 
     $line.Tags_COMMENTS = ($line.Tags | ConvertFrom-JSON).COMMENTS 
     $line.Tags_COUNTRY = ($line.Tags | ConvertFrom-JSON).COUNTRY 
     $line.'Tags_EY-REGION' = ($line.Tags | ConvertFrom-JSON).'EY-REGION' 
     $line.'Tags_IT-ENV' = ($line.Tags | ConvertFrom-JSON).'IT-ENV' 
     $line.Tags_OWNER = ($line.Tags | ConvertFrom-JSON).OWNER 
     $line.'Tags_OWNER-EMAIL' = ($line.Tags | ConvertFrom-JSON).'OWNER-EMAIL' 
     $line.Tags_SERVICELINE = ($line.Tags | ConvertFrom-JSON).SERVICELINE 
     $line.'Tags_SUB-TYPE' = ($line.Tags | ConvertFrom-JSON).'SUB-TYPE' 
     $line.Tags_TECHCONTACTS = ($line.Tags | ConvertFrom-JSON).TECHCONTACTS 
     } 
    } 
    catch {} 
} 

#write-output $info 
$file | Export-Csv 'C:\output.csv' -NoTypeInformation 
+0

「Import-Csv」を使用してください... – TheIncorrigible1

+0

1.5TB CSV !? 'Get-Content'を使って一度に処理している処理量を制限し、一度に読み込んだ行の数を制限して、メモリ不足にならないようにするのが最良です。あなたの質問。 – TheIncorrigible1

+0

申し訳ありません。私は1.5 GBのファイル(TBではない)を意味しました。一定。また、Import-CSVを使用すると処理速度が向上しました。それ以外の可能性はありますか? – Jester

答えて

0

Add-Memberはひどい性能を有しています。それで、すべてを何度も変数に保存します。あなたはより良い運がちょうど単一のパイプラインのすべてを維持し、計算された特性を持つSelect-Objectを使用している場合があります:

Get-Content -Path 'input.csv' | 
    Select-Object -Skip 2 | 
    ConvertFrom-Csv | 
    Select-Object -ErrorAction SilentlyContinue -Property *, 
     @{n = 'AdditionalInfo_StreamingEndpointName' ; e = {($_.AdditionalInfo | ConvertFrom-JSON).StreamingEndpointName}}, 
     @{n = 'AdditionalInfo_Id'     ; e = {($_.AdditionalInfo | ConvertFrom-JSON).Id}}, 
     @{n = 'AdditionalInfo_AppServicePlanUri'  ; e = {($_.AdditionalInfo | ConvertFrom-JSON).AppServicePlanUri}}, 
     @{n = 'AdditionalInfo_ImageType'    ; e = {($_.AdditionalInfo | ConvertFrom-JSON).ImageType}}, 
     @{n = 'AdditionalInfo_ServiceType'   ; e = {($_.AdditionalInfo | ConvertFrom-JSON).ServiceType}}, 
     @{n = 'AdditionalInfo_VMName'    ; e = {($_.AdditionalInfo | ConvertFrom-JSON).VMName}}, 
     @{n = 'AdditionalInfo_UsageType'    ; e = {($_.AdditionalInfo | ConvertFrom-JSON).UsageType}}, 
     @{n = 'AdditionalInfo_DatabaseAccount'  ; e = {($_.AdditionalInfo | ConvertFrom-JSON).DatabaseAccount}}, 
     @{n = 'AdditionalInfo_CollectionRid'   ; e = {($_.AdditionalInfo | ConvertFrom-JSON).CollectionRid}}, 
     @{n = 'AdditionalInfo_ResourceCategory'  ; e = {($_.AdditionalInfo | ConvertFrom-JSON).ResourceCategory}}, 
     @{n = 'Tags_displayName'      ; e = {($_.Tags | ConvertFrom-JSON).displayName}}, 
     @{n = 'Tags_ACCESSED-VIA-INTERNET'   ; e = {($_.Tags | ConvertFrom-JSON).'ACCESSED-VIA-INTERNET'}}, 
     @{n = 'Tags_APP-NAME'      ; e = {($_.Tags | ConvertFrom-JSON).'APP-NAME'}}, 
     @{n = 'Tags_APP-TYPE'      ; e = {($_.Tags | ConvertFrom-JSON).'APP-TYPE'}}, 
     @{n = 'Tags_APPTYPE'       ; e = {($_.Tags | ConvertFrom-JSON).APPTYPE}}, 
     @{n = 'Tags_CHARGECODE'      ; e = {($_.Tags | ConvertFrom-JSON).CHARGECODE}}, 
     @{n = 'Tags_COMMENTS'      ; e = {($_.Tags | ConvertFrom-JSON).COMMENTS}}, 
     @{n = 'Tags_COUNTRY'       ; e = {($_.Tags | ConvertFrom-JSON).COUNTRY}}, 
     @{n = 'Tags_EY-REGION'      ; e = {($_.Tags | ConvertFrom-JSON).'EY-REGION'}}, 
     @{n = 'Tags_IT-ENV'       ; e = {($_.Tags | ConvertFrom-JSON).'IT-ENV'}}, 
     @{n = 'Tags_OWNER'       ; e = {($_.Tags | ConvertFrom-JSON).OWNER}}, 
     @{n = 'Tags_OWNER-EMAIL'      ; e = {($_.Tags | ConvertFrom-JSON).'OWNER-EMAIL'}}, 
     @{n = 'Tags_SERVICELINE'      ; e = {($_.Tags | ConvertFrom-JSON).SERVICELINE}}, 
     @{n = 'Tags_SUB-TYPE'      ; e = {($_.Tags | ConvertFrom-JSON).'SUB-TYPE'}}, 
     @{n = 'Tags_TECHCONTACTS'     ; e = {($_.Tags | ConvertFrom-JSON).TECHCONTACTS}} | 
    Export-Csv 'C:\output.csv' -NoTypeInformation 

また言って速いかもしれません:

Get-Content -Path 'input.csv' | 
    Select-Object -Skip 2 | 
    ConvertFrom-Csv | 
    ForEach-Object { 
     $AdditionalInfo = $_.AdditionalInfo | ConvertFrom-Json; 
     $Tags = $_.Tags | ConvertFrom-Json; 
     $_ | Select-Object -Property *, 
      @{n = 'AdditionalInfo_StreamingEndpointName' ; e = {$AdditionalInfo.StreamingEndpointName}}, 
      @{n = 'AdditionalInfo_Id'     ; e = {$AdditionalInfo.Id}}, 
      ... 
    } | Export-Csv ... 

だけJSONに変換しているその方法を1行に1回

しかし、私はあなたが.Netメソッドを使用して何かを書く必要があるまともなパフォーマンスを得ると思われます。 Microsoft.VisualBasic.FileIO.TextFieldParserを使用してCSVを1行ずつ解析し、おそらくJSON.Netを使用してJsonConvert.DeserializeObject()でJSONを逆シリアル化することをお勧めします。それでも、これは超高速になるわけではありません。 1.5GBは数百万行になるはずです。 CSV全体をSQL Server 2016+にインポートし、組み込みのJSON解析を使用してクエリを使用する方がよい場合があります。

+0

Thx Baconビットに簡単にアクセスできる唯一の言語です。あなたのスクリプトは正常に動作しており、私よりもはるかに優れたコードですが、パフォーマンスはそれほど向上しませんでした。 10Mbのサンプルを完成させるのにおよそ2mnsかかるので、1.5Gbのファイルには5時間が与えられます。私はMicrosoft.VisualBasic.FileIO.TextFieldParserを試してみますが、あなたが正しいと思います。そして、これらのデータはすべてデータウェアハウスに送られるので、おそらくSQL SSISとC#を使ってファイルを解析し、まともなパフォーマンスを得るでしょう。答える時間をとってくれてありがとう! :) – Jester

+0

CSVをネストされたJSONに似たようなことができますか? –

関連する問題