Azure Docs

Azure Storage Tables Batch Operations

Azure Table Storage allows you to group multiple entity operations into a single request. This is known as a batch operation. Batch operations can improve performance by reducing the number of round trips to the server and can also be used to ensure atomicity for a set of operations.

When to Use Batch Operations

Types of Batch Operations

There are two main types of batch operations:

  1. Batch Operation (non-transactional): This type of batch operation can include operations on multiple tables and multiple entities within those tables. It does not guarantee atomicity. If one operation fails, others may still succeed.
  2. Transactional Batch Operation: This type of batch operation is restricted to operations on entities within a *single* table. It guarantees atomicity – all operations succeed or none do.

Creating a Batch Operation

The process for creating a batch operation typically involves:

  1. Initializing a batch operation object.
  2. Adding individual operations (insert, update, delete) to the batch.
  3. Executing the batch operation against the Table service.

Example (Conceptual - using Azure SDK for .NET)

The following example illustrates a transactional batch operation to update multiple entities in a single table.


using Azure;
using Azure.Data.Tables;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

// Assume 'tableName' is the name of your table
// Assume 'connectionString' is your Azure Storage connection string

TableClient tableClient = new TableClient(connectionString, tableName);

// Create or ensure the table exists
await tableClient.CreateIfNotExistsAsync();

// Sample entities to update
var entity1 = new TableEntity("PartitionKey1", "RowKey1") { { "Status", "Processed" }, { "Timestamp", DateTimeOffset.UtcNow } };
var entity2 = new TableEntity("PartitionKey1", "RowKey2") { { "Status", "Completed" }, { "Timestamp", DateTimeOffset.UtcNow } };
var entity3 = new TableEntity("PartitionKey2", "RowKey3") { { "Status", "Pending" }, { "Timestamp", DateTimeOffset.UtcNow } };

// Add entities if they don't exist (for demonstration)
await tableClient.UpsertEntityAsync(entity1, TableUpdateMode.Replace);
await tableClient.UpsertEntityAsync(entity2, TableUpdateMode.Replace);
await tableClient.UpsertEntityAsync(entity3, TableUpdateMode.Replace);

// Prepare batch operations
var batch = new TableBatchClient(tableClient);
List<Key> keysToUpdate = new List<Key>
{
    new Key("PartitionKey1", "RowKey1"),
    new Key("PartitionKey1", "RowKey2")
};

foreach (var key in keysToUpdate)
{
    // Retrieve the entity to update its properties
    var response = await tableClient.GetEntityAsync<TableEntity>(key.PartitionKey, key.RowKey);
    var entity = response.Value;

    // Modify properties
    entity["Status"] = "Updated";
    entity["Timestamp"] = DateTimeOffset.UtcNow;

    // Add the update operation to the batch
    batch.UpdateEntity(entity, ETag.All, TableUpdateMode.Replace);
}

try
{
    // Execute the transactional batch operation
    await batch.SubmitBatchAsync();
    Console.WriteLine("Batch operation completed successfully.");
}
catch (RequestFailedException ex)
{
    Console.WriteLine($"Batch operation failed: {ex.Message}");
    // Handle errors appropriately
}

// Helper class for keys
public class Key
{
    public string PartitionKey { get; }
    public string RowKey { get; }

    public Key(string partitionKey, string rowKey)
    {
        PartitionKey = partitionKey;
        RowKey = rowKey;
    }
}
            

Key Considerations

Tip: Use transactional batch operations whenever possible for operations that are logically grouped and require atomicity, especially when dealing with entities within the same partition. For scenarios involving multiple tables or when atomicity isn't strictly required, consider non-transactional batch operations to optimize network calls.

For more detailed information and specific SDK implementations, please refer to the official Azure SDK documentation for your preferred language.