PnP PowerShell を利用して SharePoint Online のリストにアイテムを作成するシリーズ。今回は、大量にアイテムを登録するときに活躍する、Batch 処理の実行方法についてです。シリーズの過去記事は、下記のリンク先。

先日、この方法を使い、リストに 15 万件ほどのデータを登録しました。

Batch 処理の利点

Batch 処理を利用すると、SharePoint に対して実行される処理の回数を減らすことができます。これにより効率よく処理を実行でき、パフォーマンスの向上も期待できます。

例えば、10 件のアイテムを登録する処理を考えてみましょう。1 件ずつ登録する非 Batch 処理では、最小でも 10 回の処理が必要になります。これが Batch 処理であれば 1 回の処理で済ませることができます。内部的には非 Batch 処理 100 回分の処理が 1 回で実行されるようです。500 件分の処理があれば、勝手に 5 回に分けて実行してくれるようなので、とても便利ですね。

Batch 処理の記述

今回は CSV ファイルを読み込んだデータを、Batch 処理でリストに登録する場面で考えてみます。

$file = "C:\...\file.csv"
$csv = Import-CSV $file

$url = "https://contoso.sharepoint.com/sites/sitename"
$listName = "ListName"

Connect-PnPOnline -Url $url -Interactive

$batch = New-PnPBatch
foreach($line in $csv){
    $itemInfo = @{}
    $itemInfo.Add("Title", $line."Title")
    $itemInfo.Add("Column1", $line."Column1")
    $itemInfo.Add("Column2", $line."Column2")

    Add-PnPListItem -List $listName -Value $itemInfo -Batch $batch
}

if($batch.Executed -eq $false -and $batch.RequestCount -gt 0){
    Invoke-PnPBatch -Batch $batch
}

Disconnect-PnPOnline

CSV のデータを foreach ループで処理しますが、この前に New-PnPBatch を利用し、Batch 処理を行いたい処理を登録しておくためのオブジェクトを作成しておきます。ループ内の Add-PnPListItem には -Batch パラメータを指定しており、これによりまとめて実行したい処理を、先ほど作成しておいたオブジェクトに登録していきます。

SharePoint に対してアイテムの登録処理が実行されるのは、Invode-PnPBatch が実行されるタイミングです。上記のサンプルでは、Batch のオブジェクトに含まれる ExecutedRequestCount の値を利用し、オブジェクトに登録された処理が実行されていない、かつ、処理が 1 件以上登録されている場合に実行するように条件を書いています。

大量に処理するときの工夫

Batch オブジェクトに追加できる処理件数に上限はなく、5,000 件でも何件でも一度に実行できるのですが、大量に実行すると SharePoint のスロットリングが発動し API 要求がブロックされてしまうことがあります。これを防ぐためには、定期的にスリープを入れるなどの工夫が有効です。

$file = "C:\...\file.csv"
$csv = Import-CSV $file

$url = "https://contoso.sharepoint.com/sites/sitename"
$listName = "ListName"

Connect-PnPOnline -Url $url -Interactive

$batch = New-PnPBatch
foreach($line in $csv){
    $itemInfo = @{}
    $itemInfo.Add("Title", $line."Title")
    $itemInfo.Add("Column1", $line."Column1")
    $itemInfo.Add("Column2", $line."Column2")

    Add-PnPListItem -List $listName -Value $itemInfo -Batch $batch

    if($batch.Executed -eq $false -and $batch.RequestCount -gt 99){
        Invoke-PnPBatch -Batch $batch

        Start-Sleep -Seconds 5
        $batch = New-PnPBatch
    }
}

if($batch.Executed -eq $false -and $batch.RequestCount -gt 0){
    Invoke-PnPBatch -Batch $batch
}

Disconnect-PnPOnline

foreach ループの中に Invoke-PnPBatch を含め、リクエストが 100 件以上溜まっているときに実行するように変更しました。Batch 処理の実行後には、Start-Sleep を入れて処理を一時的に止め、再開する前に New-PnPBatch で次の処理に備えています。

特に、「管理されたメタデータ」列を含むアイテムを登録する場合、アイテム数以上に裏側の処理がかさむようで、SharePoint のスロットリングにかかる機会が多くなるようでした。こまめに Batch 処理を実行し、中断をはさむのが良さそうですが、その分だけ全体の処理時間が長くなってしまうので、何度が試行しながら調整するのが良さそうでした。

さいごに

リスト内のアイテムを大量に処理する必要がある場合には、Batch 処理の実行方法を憶えておくと良さそうです。また、SharePoint のスロットリングについても理解しておき、処理の途中に一時中断処理を入れるなど、上手く制限を回避しながら実行できるように工夫しましょう。

PnP PowerShell の Batch 処理についての、公式ドキュメントは下記を参照してください。

Batching in PnP PowerShell | PnP PowerShell
https://pnp.github.io/powershell/articles/batching.html