Google App Engine 数据存储区为您的网络应用程序提供了可靠且可扩展的数据存储。该存储区是出于网络应用程序的考虑而设计的,着重于读取和查询性能。它存储带属性的数据实体,通过由应用程序定义的类型进行组织。通过对属性值和键设置过滤条件和排序顺序,该数据存储区可以对同一类型的实体执行查询。所有的查询都预先编入索引,便于在处理很大的数据集时快速获得结果。该数据存储区支持事务更新,使用由应用程序定义的实体分组作为分布式数据网络中事务性的单位。
App Engine 数据存储区存储数据对象(称为“实体”)并对其执行查询。一个实体具有一个或多个属性(若干受支持数据类型中某一类型的命名值)。属性可以是对另一实体的引用。
数据存储区可以在一个事务中执行多个操作,如果任一操作失败则回滚整个事务。这对于分布式网络应用程序尤其有用,在这种分布式网络应用中,多个用户可以同时访问或处理同一数据对象。
与传统数据库不同,该数据存储区使用分布式体系结构管理向超大型数据集的扩展。App Engine 应用程序可以通过描述数据对象之间的关系,以及定义查询的索引,来优化数据的分布方式。
App Engine 数据存储区具有高度的一致性,但不是关系数据库。虽然该数据存储区接口有许多与传统数据库相同的功能,但也具有独特的特征,它采用了不同的数据设计和管理方式,可以充分利用自动扩展功能。
数据存储区实体均是“无架构”的:相同类型的两个实体不必拥有相同的属性,也不必对相同的属性使用相同的值类型。在需要时,应用程序负责确保实体符合架构。为此,Python SDK 包括一个数据建模功能的丰富库,能够轻松实施架构。
在 Python API 中,模型描述实体的类型,包括其属性的类型和配置。应用程序使用 Python 类定义 Model,其中 Model 属性描述了属性。某个类型的实体由对应 Model 类的实例表示,其中实例属性则代表属性值。可以通过调用类的构造函数创建实体,然后通过调用 put() 方法进行存储。
import datetime
from google.appengine.ext import db
from google.appengine.api import users
class Employee(db.Model):
name = db.StringProperty(required=True)
role = db.StringProperty(required=True, choices=set(["executive", "manager", "producer"]))
hire_date = db.DateProperty()
new_hire_training_completed = db.BooleanProperty()
account = db.UserProperty()
e = Employee(name="",
role="manager",
account=users.get_current_user())
e.hire_date = datetime.datetime.now()
e.put()
数据存储区 API 提供两种用于查询的接口:查询对象接口和类似于 SQL 的查询接口(名为 GQL)。查询以 Model 类的实例的形式返回实体,这些 Model 类可以被修改并放回到数据存储区中。
training_registration_list = [users.User("Alfred.Smith@example.com"),
users.User("jharrison@example.com"),
users.User("budnelson@example.com")]
employees_trained = db.GqlQuery("SELECT * FROM Employee WHERE account IN :1",
training_registration_list)
for e in employees_trained:
e.new_hire_training_completed = True
db.put(e)
App Engine 数据存储区中的数据对象称为实体。一个实体具有一个或多个属性(若干数据类型中某一类型的命名值),包括整数值、浮点值、字符串、日期、二进制数据等。
每个实体还有一个唯一标识该实体的键。最简单的键具有数据存储区提供的类型和唯一的数字 ID。ID 还可以是应用程序提供的字符串。
应用程序可以使用实体的键或执行与实体属性匹配的查询,从数据存储区中抓取实体。查询可以返回零个或多个实体,并可以返回按属性值排序的结果。查询还可以限制数据存储区返回的结果的数量,以节省内存和运行时间。
与关系数据库不同,App Engine 数据存储区不要求指定类型的所有实体要有相同的属性。应用程序可指定并强制其数据模型使用 SDK 附带的库或其自己的代码。
一个属性可具有一个或多个值。具有多个值的属性可具有混合类型的值。对具有多个值的属性进行查询可测试是否有任何值满足查询条件。这样可以使这些属性能够用于测试成员身份。
App Engine 数据存储区查询对某一指定类型(数据类)的每个实体进行操作。它对实体属性值和键指定零个或多个过滤条件,以及零个或多个排序顺序。如果一个实体对于查询的过滤条件和排序顺序中所提及的每个属性都具有至少一个值(可能为 null),且属性值满足所有过滤条件,那么将返回该实体作为查询的结果。
每个数据存储区查询都使用一个索引,即包含按指定顺序排列的查询结果的表格。App Engine 应用程序会在一个配置文件中定义其索引。开发网络服务器在遇到未配置索引的查询时会自动为该文件添加建议。您可以在上传该应用程序之前编辑该文件,以手动调整索引。当应用程序对数据存储区实体做出更改时,数据存储区会使用正确的结果更新索引。当应用程序执行查询时,数据存储区会直接从相应的索引中抓取结果。
该机制可支持许多查询,且适用于大部分应用程序。然而,该机制不支持您可能惯用的其他数据库技术中的一些查询类型。
在 App Engine 数据存储区中,所有创建、更新或删除实体的尝试都可以在一个事务中进行。事务可确保对实体所做的所有更改都保存到数据存储区中,或者,在失败的情况下不做任何更改。这样便可确保实体中数据的一致性。
您可以使用事务 API 在单一事务中对一个实体执行多个操作。例如,假设您要使对象中的计数器域递增。为此,您需要读取计数器的值,计算新的值,然后存储值。如果没有事务,那么在您读取值和更新值之间,可能有另一进程使计数器递增,这会导致应用程序覆盖已更新的值。在单一事务中进行读取、计算和写入操作可确保没有其他进程干扰递增。
您可以在单一事务中对多个实体进行更改。为了支持这种做法,App Engine 需要预先了解哪些实体将一起更新,从而使用支持事务的方式来存储这些实体。您在创建实体时,必须声明这一实体与另一实体同属一个实体组。在一个事务中抓取、创建、更新或删除的所有实体都必须位于同一实体组中。
实体组是由实体之间关系的层次结构定义的。要在组中创建实体,您应声明该实体是组中现有的另一实体的子实体。另一实体为父实体。不通过父实体创建的实体是根实体。如果一个根实体没有任何子实体,则其所在的实体组中只有这一个实体。每个实体都有一条从根实体到其自身的父实体-子实体关系路径(最短的路径没有父实体)。该路径是实体完整键中必不可少的一部分。完整的键可以用路径中各实体的类型以及 ID 或键名来表示。
数据存储区使用开放式并发来管理事务。在一个应用程序实例将更改应用到实体组中的实体时,对于该组中任何实体的所有其他更新尝试都会立即失败。应用程序可再次尝试事务,将其应用到更新的数据。
对于数据存储区 API 的每次调用都会计算在数据存储区 API 调用配额内。请注意,有些库的调用会导致对基础数据存储区 API 的多次调用。
由应用程序发送到数据存储区的数据会计算在数据发送到(数据存储区)API 配额内。应用程序从数据存储区接收的数据都会计算在数据接收自(数据存储区)API 配额内。
应用程序当前存储在数据存储区中的数据总量不得超过存储的数据(可调整)配额。这包括实体属性和键,但不包括索引。
数据存储区操作消耗的 CPU 时间不得超过以下配额:
有关配额的详细信息,请参阅配额以及管理控制台的“配额详细信息”部分。
除了配额以外,使用数据存储区还需遵循以下限制:
| 限制 | 值 |
|---|---|
| 最大实体大小 | 1 兆字节 |
| 实体的索引中值的最大数量 |
1,000 个值 |
| 批量放置或批量删除中实体的最大数量 | 500 个实体 |
| 批量获取中实体的最大数量 | 1,000 个实体 |
| 查询的最大结果偏移量 | 1,000 |
|
|