Azure Storage Tableがあり、3k以上のレコードがあります。
テーブル内のすべての行を削除する最も効率的な方法は何ですか?
3000レコードの場合、最も簡単な方法は テーブルを削除する です。ただし、テーブルを削除すると、その時点では削除されず、ある種のキューに入れられて削除され、実際にはしばらくしてから削除されることに注意してください。この時間は、システムの負荷+テーブル内のエンティティの数によって異なります。この間、このテーブルを再作成したり、このテーブルを使用したりすることはできません。
テーブルを使い続けることが重要な場合、他の唯一のオプションはエンティティを削除することです。削除を高速化するには、 Entity Batch Transactions
を使用してエンティティの削除を確認できます。ただし、エンティティを削除するには、最初にエンティティをフェッチする必要があります。エンティティの削除にはこれら2つの属性のみが必要であるため、すべての属性をフェッチするのではなく、エンティティのPartitionKey
属性とRowKey
属性のみをフェッチすることで、フェッチプロセスを高速化できます。
私はこのようなものを使用します。キーを日付で分割します。ケースが異なる場合があります。
async Task Main()
{
var startDate = new DateTime(2011, 1, 1);
var endDate = new DateTime(2012, 1, 1);
var account = CloudStorageAccount.Parse("connString");
var client = account.CreateCloudTableClient();
var table = client.GetTableReference("TableName");
var dates = Enumerable.Range(0, Math.Abs((startDate.Month - endDate.Month) + 12 * (startDate.Year - endDate.Year)))
.Select(offset => startDate.AddMonths(offset))
.ToList();
foreach (var date in dates)
{
var key = $"{date.ToShortDateString()}";
var query = $"(PartitionKey eq '{key}')";
var rangeQuery = new TableQuery<TableEntity>().Where(query);
var result = table.ExecuteQuery<TableEntity>(rangeQuery);
$"Deleting data from {date.ToShortDateString()}, key {key}, has {result.Count()} records.".Dump();
var allTasks = result.Select(async r =>
{
try
{
await table.ExecuteAsync(TableOperation.Delete(r));
}
catch (Exception e) { $"{r.RowKey} - {e.ToString()}".Dump(); }
});
await Task.WhenAll(allTasks);
}
}
これはデータの構造によって異なりますが、すべてのレコードのクエリを作成できる場合は、それぞれを TableBatchOperation
に追加して、一度に実行できます。
これは、同じパーティションキー内ですべての結果を取得する例であり、 AzureテーブルストレージとVisual Studio接続サービスの使用を開始する方法 から適応されています。
// query all rows
CloudTable peopleTable = tableClient.GetTableReference("myTableName");
var query = new TableQuery<MyTableEntity>();
var result = await remindersTable.ExecuteQuerySegmentedAsync(query, null);
// Create the batch operation.
TableBatchOperation batchDeleteOperation = new TableBatchOperation();
foreach (var row in result)
{
batchDeleteOperation.Delete(row);
}
// Execute the batch operation.
await remindersTable.ExecuteBatchAsync(batchDeleteOperation);
次の関数を使用して、最初にすべてのパーティションキーをキューに入れ、次にキーをループして100のバッチですべての行を削除します。
Queue queue = new Queue();
queue.Enqueue("PartitionKeyTodelete1");
queue.Enqueue("PartitionKeyTodelete2");
queue.Enqueue("PartitionKeyTodelete3");
while (queue.Count > 0)
{
string partitionToDelete = (string)queue.Dequeue();
TableQuery<TableEntity> deleteQuery = new TableQuery<TableEntity>()
.Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partitionToDelete))
.Select(new string[] { "PartitionKey", "RowKey" });
TableContinuationToken continuationToken = null;
do
{
var tableQueryResult = await myTable.ExecuteQuerySegmentedAsync(deleteQuery, continuationToken);
continuationToken = tableQueryResult.ContinuationToken;
// Split into chunks of 100 for batching
List<List<TableEntity>> rowsChunked = tableQueryResult.Select((x, index) => new { Index = index, Value = x })
.Where(x => x.Value != null)
.GroupBy(x => x.Index / 100)
.Select(x => x.Select(v => v.Value).ToList())
.ToList();
// Delete each chunk of 100 in a batch
foreach (List<TableEntity> rows in rowsChunked)
{
TableBatchOperation tableBatchOperation = new TableBatchOperation();
rows.ForEach(x => tableBatchOperation.Add(TableOperation.Delete(x)));
await myTable.ExecuteBatchAsync(tableBatchOperation);
}
}
while (continuationToken != null);
}