PowerShellスクリプトが遅い原因の知識マップ(知識グラフ)
type: Dataset
description: PowerShellの配列は固定長のため$array += $itemは毎回全要素をコピーし、文字列の+=も不変な文字列を毎回作り直すため、どちらも件数の2乗に比例して遅くなる。この2乗の劣化はList[T]・foreach文の出力集約・StringBuilderや-joinで避けられ、二重ループでの突合はハッシュテーブル化で線形探索の比較回数を大きく減らせる、費用対効果の最も高い改善である。Get-Contentの読み方の使い分けや遅延列挙、Get-ChildItemの-Filterによる絞り込み、Format系コマンドレットを途中に挟まないことも効果があり、これらの効果はMeasure-Commandで検証する。並列化はアルゴリズムそのものを直してから最後に検討すべき手段で、計算量がO(n^2)のまま並列化しても効果は限られる。

配列の+=によるコピー
type: Concept
definition: PowerShellの配列が固定長であるために、要素追加のたびに新しい配列を作って全要素をコピーする書き方。
alternative label: $array += $item
alternative label: 配列への追加
may cause: 件数の2乗に比例する速度劣化
verified by: Measure-Command

ハッシュテーブルによる突合
type: Concept
definition: 二重ループの中でWhere-Objectなどによる全件走査を行う突合を、索引(ハッシュテーブル)を1度だけ作りキーで引く形に置き換える高速化手法。
alternative label: Hashtable Lookup
alternative label: Group-Object -AsHashTable
mitigates: 二重ループの線形探索による突合
verified by: Measure-Command
should precede: ForEach-Object -Parallel

件数の2乗に比例する速度劣化
type: Concept
definition: 配列や文字列の+=など、毎回全体をコピーする操作を繰り返すことで、処理時間が件数の2乗に比例して悪化する現象。
alternative label: O(n^2)の劣化

文字列の+=による再生成
type: Concept
definition: 文字列が不変(immutable)であるために、連結のたびに新しい文字列インスタンスを生成する書き方。
alternative label: $s += "..."
may cause: 件数の2乗に比例する速度劣化

List[T](System.Collections.Generic.List)
type: Concept
definition: 要素の追加が定数時間で行える.NETの可変長コレクション型で、配列の+=の代わりに.Add()で要素を足す。
alternative label: List<T>
alternative label: Generic List
mitigates: 件数の2乗に比例する速度劣化
should precede: ForEach-Object -Parallel

foreach文
type: Concept
definition: メモリ上のコレクションを1件ずつ処理する制御構文で、1件あたりのオーバーヘッドがパイプラインより小さく、ループ全体の出力をそのまま変数に集約できる。
alternative label: foreach Statement
mitigates: 件数の2乗に比例する速度劣化

StringBuilder / -join
type: Concept
definition: 不変な文字列の+=連結を避け、可変バッファでの組み立て(StringBuilder)や配列の一括結合(-join)によって文字列連結を高速化する手段。
alternative label: System.Text.StringBuilder
mitigates: 件数の2乗に比例する速度劣化

二重ループの線形探索による突合
type: Concept
definition: 内側のループで毎回Where-Objectなどによる全件走査を行う突合方法で、比較回数が受注件数×マスター件数のように積になる。
alternative label: Where-Objectによる全件走査

遅延列挙
type: Concept
definition: 巨大な入力を全件メモリに読み込まず1件ずつ列挙する仕組みで、[System.IO.File]::ReadLinesなどが該当し、foreach文と組み合わせるとメモリを使わずに処理できる。
alternative label: Lazy Enumeration
alternative label: File.ReadLines
mitigates: 1行ごとのオブジェクト生成コスト

Get-Content
type: Concept
definition: ファイルを読み込むコマンドレットで、既定では改行区切りで1行ずつオブジェクトとして返し、-Rawで一括読み込み、-ReadCountでまとめ読みができる。
alternative label: ファイルの行読み込み
verified by: Measure-Command
may cause: 1行ごとのオブジェクト生成コスト

Measure-Command
type: Concept
definition: スクリプトブロックやコマンドの実行時間を計測してTimeSpanを返すコマンドレットで、測定対象の出力自体は破棄され結果に含まれない。
alternative label: 実行時間の計測

Get-ChildItemの-Filter
type: Concept
definition: Get-ChildItemのプロバイダーがオブジェクト取得時に適用する絞り込みパラメーターで、取得後にWhere-Objectで捨てるより効率的とされる。
alternative label: プロバイダー側の絞り込み
verified by: Measure-Command
mitigates: 取得後にWhere-Objectで捨てる絞り込み

Format-Table/Format-List
type: Concept
definition: PowerShellの結果を画面表示用に整形するコマンドレットで、通すと結果が元のオブジェクトではなく表示用のフォーマット情報に変わる。
alternative label: Format-Table / Format-List
alternative label: Format系コマンドレット
may cause: 後続パイプラインの破壊
verified by: Measure-Command

後続パイプラインの破壊
type: Concept
definition: Format系コマンドレットを出力の途中に挟むことで、後続のコマンドが受け取るオブジェクトが表示用のフォーマットオブジェクトに変わってしまい処理が壊れること。
alternative label: Format系による後続処理の破壊

Write-Progress
type: Concept
definition: コマンドの進行状況をホストの進捗表示として出すコマンドレットで、リダイレクト可能なデータストリームではなく、ログには残せない。
alternative label: 進捗表示
may cause: 進捗更新の描画コスト
verified by: Measure-Command

進捗更新の描画コスト
type: Concept
definition: ループのたびにWrite-Progressで進捗を更新する描画コストで、更新頻度が高いと処理時間そのものより重くなることがある。
alternative label: Write-Progressの描画負荷

ForEach-Object -Parallel
type: Concept
definition: PowerShell 7.0で追加された、入力の各要素を別のランスペースで並列実行するパラメーターセット。
alternative label: 並列パラメーターセット
not recommended for: 件数の2乗に比例する速度劣化

取得後にWhere-Objectで捨てる絞り込み
type: Concept
definition: Get-ChildItemなどでいったん全件取得してからWhere-Objectで不要な項目を捨てる非効率な絞り込み方法。
alternative label: Post-Filter Discard

1行ごとのオブジェクト生成コスト
type: Concept
definition: Get-Contentが既定で1行ずつオブジェクトを生成することによるコストで、巨大ファイルを読み込む際に支配的になる。
alternative label: Get-Contentの行オブジェクト化コスト

subject: 配列の+=によるコピー
predicate: mayCause
object: 件数の2乗に比例する速度劣化
description: n件を+=で追加すると発生する要素コピーの総数はn(n-1)/2になり、件数の2乗に比例して遅くなる
evidence: about arrays
verified at: 2026-08-01
certainty: established

subject: 文字列の+=による再生成
predicate: mayCause
object: 件数の2乗に比例する速度劣化
description: 文字列は不変なので$s += "line"は毎回新しい文字列を作り、配列の+=と同じ理由で件数の2乗に比例して遅くなる
evidence: system.text.stringbuilder
verified at: 2026-08-01
certainty: established

subject: List[T](System.Collections.Generic.List)
predicate: mitigates
object: 件数の2乗に比例する速度劣化
description: List[T]の.Add()は定数時間の追加であるため、件数が増えても2乗の劣化を避けられる
evidence: about arrays
verified at: 2026-08-01
certainty: established

subject: foreach文
predicate: mitigates
object: 件数の2乗に比例する速度劣化
description: foreach文の出力をそのまま変数へ集約する書き方(PowerShellらしい書き方)も配列の+=を避けられる
evidence: about foreach
verified at: 2026-08-01
certainty: established

subject: StringBuilder / -join
predicate: mitigates
object: 件数の2乗に比例する速度劣化
description: StringBuilderの可変バッファでの組み立てや-joinによる一括結合は、文字列版の2乗の劣化を避けられる
evidence: system.text.stringbuilder
verified at: 2026-08-01
certainty: established

subject: ハッシュテーブルによる突合
predicate: mitigates
object: 二重ループの線形探索による突合
description: 索引を1度だけ作りキーで引く形にすることで、二重ループの全件比較を件数にほぼ比例する回数まで減らせる
evidence: group-object
verified at: 2026-08-01
certainty: established

subject: foreach文
predicate: requires
object: 遅延列挙
description: 巨大なファイルをメモリに載せずforeach文で処理するには、ReadLinesのような遅延列挙のIEnumerableを渡す必要がある。丸かっこ内でコマンドの実行結果を評価すると全件がメモリに載る
evidence: about foreach
verified at: 2026-08-01
certainty: context-dependent

subject: Get-Content
predicate: verifiedBy
object: Measure-Command
description: 読み込み方式(既定・-Raw・-ReadCount)ごとの速度差はMeasure-Commandで確認できる
evidence: measure-command
verified at: 2026-08-01
certainty: established

subject: Get-ChildItemの-Filter
predicate: verifiedBy
object: Measure-Command
description: -Filterの有無による速度差はMeasure-Commandで確認できる
evidence: measure-command
verified at: 2026-08-01
certainty: established

subject: ハッシュテーブルによる突合
predicate: verifiedBy
object: Measure-Command
description: 突合の高速化効果はMeasure-Commandで二重ループ版と比較して確認できる
evidence: measure-command
verified at: 2026-08-01
certainty: established

subject: 配列の+=によるコピー
predicate: verifiedBy
object: Measure-Command
description: 配列の+=とList[T]の速度差はMeasure-Commandで比較できる。ただし出力は破棄され表示コストは含まれない点に注意する
evidence: measure-command
verified at: 2026-08-01
certainty: established

subject: Format-Table/Format-List
predicate: mayCause
object: 後続パイプラインの破壊
description: Format系コマンドレットが生成するフォーマットオブジェクトをパイプラインの途中に挟むと、後続の処理が壊れる
evidence: format-table
verified at: 2026-08-01
certainty: established

subject: Write-Progress
predicate: mayCause
object: 進捗更新の描画コスト
description: ループのたびに進捗を更新すると、描画コストが処理時間そのものを上回ることがある
evidence: write-progress
verified at: 2026-08-01
certainty: established

subject: ハッシュテーブルによる突合
predicate: shouldPrecede
object: ForEach-Object -Parallel
description: 突合のハッシュ化などアルゴリズムの改善を先に行ってから、並列化を検討すべきである
evidence: foreach-object
verified at: 2026-08-01
certainty: established

subject: List[T](System.Collections.Generic.List)
predicate: shouldPrecede
object: ForEach-Object -Parallel
description: 配列操作の改善などアルゴリズムの修正を先に行ってから、並列化を検討すべきである
evidence: foreach-object
verified at: 2026-08-01
certainty: established

subject: ForEach-Object -Parallel
predicate: notRecommendedFor
object: 件数の2乗に比例する速度劣化
description: 計算量がO(n^2)のまま並列化しても、コア数の分しか速くならず効果は限定的である
evidence: foreach-object
verified at: 2026-08-01
certainty: established

subject: Get-ChildItemの-Filter
predicate: mitigates
object: 取得後にWhere-Objectで捨てる絞り込み
description: -Filterで取得時に絞り込むことで、全件取得してからWhere-Objectで捨てる非効率な方法を避けられる
evidence: get-childitem
verified at: 2026-08-01
certainty: established

subject: Get-Content
predicate: mayCause
object: 1行ごとのオブジェクト生成コスト
description: Get-Contentは既定で1行ずつオブジェクトを生成するため、巨大ファイルではこのコストが支配的になる
evidence: get-content
verified at: 2026-08-01
certainty: established

subject: 遅延列挙
predicate: mitigates
object: 1行ごとのオブジェクト生成コスト
description: [System.IO.File]::ReadLinesのような逐次列挙は、1行ごとのオブジェクト生成コストを回避できる
evidence: system.io.file.readlines
verified at: 2026-08-01
certainty: established

subject: Format-Table/Format-List
predicate: verifiedBy
object: Measure-Command
description: Format系コマンドレットを挟むことによる処理コストもMeasure-Commandで確認できる
evidence: measure-command
verified at: 2026-08-01
certainty: established

subject: Write-Progress
predicate: verifiedBy
object: Measure-Command
description: 進捗更新の描画コストもMeasure-Commandで比較できる
evidence: measure-command
verified at: 2026-08-01
certainty: established