Cosmos DBにストアドプロシージャでバルクインサート
前回は1ドキュメント/APIでインポートしました。
Cosmos DBはJavaScriptでストアドプロシージャを記述することができますので、ストアドプロシージャを使って一括でインポートしてみます。
今回290件ほどデータを追加していますが、個別追加はRUが6.2-6.6/件くらい(合計1800超)、一括だと1227.86でした。RUも処理時間もお得ですね。
ストアドプロシージャは、Azure Cosmos DB server-side programming: Stored procedures, database triggers, and UDFs の Example: Bulk importing data into a database program にあるサンプルコードをコピーしてbulkImport.jsとして保存して使用。
bulkImport.js
function bulkImport(docs) { var collection = getContext().getCollection(); var collectionLink = collection.getSelfLink(); var count = 0; if (!docs) throw new Error("The array is undefined or null."); var docsLength = docs.length; if (docsLength == 0) { getContext().getResponse().setBody(0); } tryCreate(docs[count], callback); function tryCreate(doc, callback) { var isAccepted = collection.createDocument(collectionLink, doc, callback); if (!isAccepted) getContext().getResponse().setBody(count); } function callback(err, doc, options) { if (err) throw err; count++; if (count >= docsLength) { getContext().getResponse().setBody(count); } else { tryCreate(docs[count], callback); } } }
PowerShellではストアドプロシージャをAPIで登録し、FOR JSON PATH付きの取得結果をBodyに設定するだけです。ただ、結果なJSONをそのままストアドに渡すと1番目のみしかdocsに入ってこないので、結果を新しい配列に入れてネストさせてます。 過去のブログに記載されているコードと重複している部分もありますが、まるっと掲載。
# いろいろExec function exec($endPoint, $masterKey, $resourceType, $resourceLink, $bodyJson, $uri) { $verb = "POST" $dateTime = [DateTime]::UtcNow.ToString("r") $authHeader = Generate-MasterKeyAuthorizationSignature -verb $verb -resourceLink $resourceLink -resourceType $resourceType -key $masterKey -keyType "master" -tokenVersion "1.0" -dateTime $dateTime $header = @{authorization=$authHeader;"x-ms-version"="2017-02-22";"x-ms-date"=$dateTime} $contentType= "application/json" $queryUri = "$endPoint$uri" Echo $queryUri $result = Invoke-RestMethod -Method $verb -ContentType $contentType -Uri $queryUri -Headers $header -Body $bodyJson $result | ConvertTo-Json -Depth 10 } # キーを取得 $keys = Invoke-AzureRmResourceAction -Action listKeys -ResourceType "Microsoft.DocumentDb/databaseAccounts" -ApiVersion "2016-03-31" -ResourceGroupName "RG01" -Name "cosmosdbtest" # 作るモノの設定 $endPoint = "https://cosmosdbtest.documents.azure.com/" $dataBaseId = "hogedb1" $collectionId = "hogecoll1" $storedProcedureId = "bulkImport" # ストアド登録 $js = Get-Content "bulkImport.js" $json = @{ "id"="$StoredProcedureId"; "body"="$js"; } | ConvertTo-Json exec -EndPoint $endPoint -DataBaseId $dataBaseId -MasterKey $keys.primaryMasterKey -ResourceType "sprocs" -ResourceLink "dbs/$databaseId/colls/$collectionId" -BodyJson $json -Uri "dbs/$databaseId/colls/$collectionId/sprocs" # データ登録 Set-Location SQLSERVER:\SQL\localhost\DEFAULT\Databases\AdventureWorks2016CTP3 $result = Invoke-Sqlcmd -InputFile "ex2.sql" $json = "[" + $result.ItemArray + "]"; exec -EndPoint $endPoint -DataBaseId $dataBaseId -MasterKey $keys.primaryMasterKey -ResourceType "sprocs" -ResourceLink "dbs/$databaseId/colls/$collectionId/sprocs/$storedProcedureId" -BodyJson $json -Uri "dbs/$databaseId/colls/$collectionId/sprocs/$storedProcedureId"
- ex2.sqlは、Cosmos DBにSQL Serverのデータをインポートに記載
- Generate-MasterKeyAuthorizationSignatureは、Cosmos DB はじめましたに記載
これでデータ準備も含めたCosmos DBとPowerShellの3部作は一応終わりの予定。