如何在 Python 中使用表存储

Tip

本文内容适用于原始的基本 Azure 表存储。 但是,公共预览版中现提供 Azure 表存储的高级版本,该版本提供优化了吞吐量的表、全局分发和自动化辅助索引。 若要详细了解和体验高级版,请查看 Azure Cosmos DB:表 API。 本文中的编程语言在高级版中尚不受支持,但在将来会添加该支持。

本指南介绍如何使用用于 Python 的 Microsoft Azure 存储 SDK 在 Python 中执行常见 Azure 表存储方案。 涉及的情景包括创建和删除表、插入和查询实体。

在浏览本教程中的方案时,可能想要参考用于 Python API 的 Microsoft Azure 存储 SDK 参考

什么是表服务?

Azure 表存储服务可存储大量结构化数据。 该服务是一个 NoSQL 数据存储,接受来自 Azure 云内部和外部的通过验证的呼叫。 Azure 表最适合存储结构化非关系型数据。 表服务的常见用途包括:

  • 存储 TB 量级的结构化数据,能够为 Web 规模应用程序提供服务
  • 存储无需复杂联接、外键或存储过程,并且可以对其进行非规范化以实现快速访问的数据集
  • 使用聚集索引快速查询数据
  • 使用 OData 协议和 LINQ 查询以及 WCF 数据服务 .NET 库访问数据

可以使用表服务来存储和查询大型结构化非关系型数据集,并且表会随着需求的增加而扩展。

表服务概念

表服务包含以下组件:

表服务组件示意图

  • URL 格式: 代码使用此地址格式对帐户中的表进行寻址:
    http://<storage account>.table.core.chinacloudapi.cn/<table>

    可以直接使用此地址和 OData 协议来访问 Azure 表。 有关详细信息,请参阅 OData.org

  • 存储帐户: 对 Azure 存储服务的所有访问都要通过存储帐户来完成。 有关存储帐户容量的详细信息,请参阅 Azure 存储可伸缩性和性能目标
  • :表是实体的集合。 表不对实体强制实施架构,这意味着单个表可以包含具有不同属性集的实体。 一个存储帐户可以包含的表数仅受存储帐户容量限制。
  • 实体:与数据库行类似,一个实体就是一组属性。 一个实体的大小可达 1 MB。
  • 属性:属性是名称/值对。 每个实体最多可包含 252 个用于存储数据的属性。 每个实体还包含 3 个系统属性,分别指定分区键、行键和时间戳。 对具有相同分区键的实体的查询速度将更快,并且可以在原子操作中插入/更新这些实体。 一个实体的行键是它在一个分区内的唯一标识符。

有关命名表和属性的详细信息,请参阅 了解表服务数据模型

创建 Azure 存储帐户

创建第一个 Azure 存储帐户的最简单方法是使用 Azure 门户。 若要了解更多信息,请参阅 创建存储帐户

还可使用 Azure PowerShellAzure CLI适用于 .NET 的存储资源提供程序客户端库创建 Azure 存储帐户。

如果暂时不想创建存储帐户,也可以使用 Azure 存储模拟器在本地环境中运行和测试代码。 有关详细信息,请参阅 使用 Azure 存储模拟器进行开发和测试

安装用于 Python 的 Microsoft Azure 存储 SDK

创建存储帐户后,下一步就是安装用于 Python 的 Microsoft Azure 存储 SDK。 有关安装 SDK 的详细信息,请参阅 GitHub 上用于 Python 的存储 SDK 存储库中的 README.rst 文件。

创建表

若要使用 Python 中的 Azure 表服务,必须导入 TableService 模块。 因为要使用表实体,因此还需要[实体][ py_Entity]类。 将此代码添加到 Python 文件顶部附近,以便同时导入:

from azure.storage.table import TableService, Entity

创建 TableService 对象,传入存储帐户名和帐户密钥。 将 myaccountmykey 替换为帐户名和密钥,并调用create_table,在 Azure 存储中创建表。

table_service = TableService(account_name='myaccount', account_key='mykey',endpoint_suffix='core.chinacloudapi.cn')

table_service.create_table('tasktable')

向表中添加条目

如果要添加实体,首先创建一个表示实体的对象,然后将该对象传递给 TableService.insert_entity 方法。 实体对象可以是一个实体类型的字典和对象,且可定义实体的属性名和值。 除了为实体定义的任何其他属性外,每个实体还必须包含 PartitionKey 和 RowKey 属性。

此示例将创建一个表示实体的字典对象,并将该对象传递给 insert_entity 方法以将其添加到表:

task = {'PartitionKey': 'tasksSeattle', 'RowKey': '001', 'description' : 'Take out the trash', 'priority' : 200}
table_service.insert_entity('tasktable', task)

此示例将创建一个实体对象,并将该对象传递给 insert_entity 方法以将其添加到表:

task = Entity()
task.PartitionKey = 'tasksSeattle'
task.RowKey = '002'
task.description = 'Wash the car'
task.priority = 100
table_service.insert_entity('tasktable', task)

PartitionKey 和 RowKey

必须为每个实体同时指定 PartitionKey 和 RowKey 属性。 这些是实体的唯一标识符,它们一起构成了实体的主键。 由于只对这些属性编制了索引,因此可使用这些值进行查询,速度比查询任何其他实体属性都要快。

表服务使用 PartitionKey 在存储节点中智能分发。 具有相同的 PartitionKey 的实体存储在同一个节点上。 RowKey 是实体在其所属分区内的唯一 ID。

更新条目

若要更新实体的所有属性值,请调用 update_entity 方法。 此示例演示如何使用更新版本替换现有实体:

task = {'PartitionKey': 'tasksSeattle', 'RowKey': '001', 'description' : 'Take out the garbage', 'priority' : 250}
table_service.update_entity('tasktable', task)

如果要更新的实体不存在,更新操作将失败。 如果要存储实体,无论它是否已存在,请使用 insert_or_replace_entity。 在下面的示例中,第一次调用会替换现有实体。 第二个调用将插入新实体,因为表中不存在具有指定 PartitionKey 和 RowKey 的实体。

# Replace the entity created earlier
task = {'PartitionKey': 'tasksSeattle', 'RowKey': '001', 'description' : 'Take out the garbage again', 'priority' : 250}
table_service.insert_or_replace_entity('tasktable', task)

# Insert a new entity
task = {'PartitionKey': 'tasksSeattle', 'RowKey': '003', 'description' : 'Buy detergent', 'priority' : 300}
table_service.insert_or_replace_entity('tasktable', task)
Tip

update_entity 方法将替换现有实体的所有属性和值,还可将其用于从现有实体中删除属性。 可以使用 merge_entity 方法更新含新的或修改后的属性值的现有实体,而无需彻底替换该实体。

修改多个实体

若要确保通过表服务进行原子处理,可以批量同时提交多个操作。 首先,使用 TableBatch 类将多个操作添加到单个批处理中。 接下来,调用 TableService.commit_batch 以原子操作的形式提交操作。 批处理中要修改的实体必须位于同一分区。

该示例将两个实体一起添加到批处理中:

from azure.storage.table import TableBatch
batch = TableBatch()
task004 = {'PartitionKey': 'tasksSeattle', 'RowKey': '004', 'description' : 'Go grocery shopping', 'priority' : 400}
task005 = {'PartitionKey': 'tasksSeattle', 'RowKey': '005', 'description' : 'Clean the bathroom', 'priority' : 100}
batch.insert_entity(task004)
batch.insert_entity(task005)
table_service.commit_batch('tasktable', batch)

还可以通过上下文管理器语法来使用批处理:

task006 = {'PartitionKey': 'tasksSeattle', 'RowKey': '006', 'description' : 'Go grocery shopping', 'priority' : 400}
task007 = {'PartitionKey': 'tasksSeattle', 'RowKey': '007', 'description' : 'Clean the bathroom', 'priority' : 100}

with table_service.batch('tasktable') as batch:
    batch.insert_entity(task006)
    batch.insert_entity(task007)

查询条目

要查询表中的实体,请将 PartitionKey 和 RowKey 传递给 TableService.get_entity 方法。

task = table_service.get_entity('tasktable', 'tasksSeattle', '001')
print(task.description)
print(task.priority)

查询一组条目

在筛选器字符串中提供 filter 参数,可以查询一组实体。 此示例通过对 PartitionKey 应用筛选器来查找 Seattle 中的所有任务:

tasks = table_service.query_entities('tasktable', filter="PartitionKey eq 'tasksSeattle'")
for task in tasks:
    print(task.description)
    print(task.priority)

查询条目属性的子集

还可以限制查询中每个实体所返回的属性。 此方法称为“投影”,可减少带宽并提高查询性能,尤其适用于大型实体或结果集。 使用 select 参数并传递希望返回给客户端的属性的名称。

以下代码中的查询只返回表中实体的说明。

Note

下面的代码段仅对 Azure 存储有效。 但不受存储模拟器支持。

tasks = table_service.query_entities('tasktable', filter="PartitionKey eq 'tasksSeattle'", select='description')
for task in tasks:
    print(task.description)

删除实体

可通过将实体的 PartitionKey 和 RowKey 传递给 delete_entity 方法将其删除。

table_service.delete_entity('tasktable', 'tasksSeattle', '001')

删除表

如果不再需要某个表或其内的任何实体,请调用 delete_table 方法将该表从 Azure 存储中永久删除。

table_service.delete_table('tasktable')

后续步骤