二级索引在创建时是否会锁定任何内容?
Does a Secondry index lock anything when it is being created?
给定以下 table 架构:
CREATE TABLE Record (
-- uuidv4
recordId STRING(36) NOT NULL,
-- uuidv4
userId STRING(36),
isActive BOOL
lastUpdate TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)
...
) PRIMARY KEY (recordId)
CREATE NULL_FILTERED INDEX RecordByUser
ON Record (userId, isActive)
对于创建的每条记录,我们都会创建一条记录(在索引中),以便能够通过用户 ID 获取用户的所有记录。根据可能需要的内容,可能会有一个带有附加信息列的额外 STORING
子句。
我的理解是,当我向 Record
table 添加记录时,Spanner 将触发对索引的写入。由于索引是非交错的,因此数据本身可能与原始记录具有不同的位置。
在该假设下,写入二级索引是否会锁定 Record
table 直到完成或一个不影响另一个?
我猜它们是完全独立的,因为可以在事后创建索引并且 Spanner 将触发回填操作,该操作不会影响 Record
table 的运行状态.
写入索引的行为必须从节点获取一些资源,所以我想这确实是一个限制。在 Record
table 的高写入场景下,我们还将有效地为索引 table RecordByUser
调用第二次写入,消耗更多的节点写入吞吐能力。
因此添加到二级索引的行为不需要对源进行任何锁定 table(在本例中为 Record
)。主要关注的是写入吞吐量和这些写入的任何热点。例如,如果我们将时间戳记作为索引的第一部分进行索引,则对索引的写入会聚集在一起。我的理解对吗?
在现有 table 上创建索引的过程中,回填进程是否对索引持有独占锁,例如 Postgres:
https://www.postgresql.org/docs/current/index-locking.html
或者在回填发生时,新的写入可以在二级索引创建期间进入索引吗?
我可以想象一个在 spanners 端的回填过程,它拍摄一个读取快照并开始写入。给定 Spanners fancy clocks,如果它在索引中遇到比它试图写入的行更新的行,它只会将旧行丢弃在地板上并继续。
感谢提问。 Google 工程师在此寻求帮助。
+1 到 chainicko@ 通用锁定机制的答案。尽管回填仍然是 运行.
,但您仍然可以 read/write 原来的 table,因此它没有“锁定”
Read/query 在回填期间不允许索引本身。但允许写入原始 table。新写入同时添加到索引中。回填后,Spanner 将确保在查询时只显示最新数据。
关于“在时间戳上建立索引作为索引的第一部分”的示例,由于它在索引上创建了一个热点,所以它仍然会对整个系统产生负面影响,即使它不会锁定原始 table.
给定以下 table 架构:
CREATE TABLE Record (
-- uuidv4
recordId STRING(36) NOT NULL,
-- uuidv4
userId STRING(36),
isActive BOOL
lastUpdate TIMESTAMP NOT NULL OPTIONS (allow_commit_timestamp=true)
...
) PRIMARY KEY (recordId)
CREATE NULL_FILTERED INDEX RecordByUser
ON Record (userId, isActive)
对于创建的每条记录,我们都会创建一条记录(在索引中),以便能够通过用户 ID 获取用户的所有记录。根据可能需要的内容,可能会有一个带有附加信息列的额外 STORING
子句。
我的理解是,当我向 Record
table 添加记录时,Spanner 将触发对索引的写入。由于索引是非交错的,因此数据本身可能与原始记录具有不同的位置。
在该假设下,写入二级索引是否会锁定 Record
table 直到完成或一个不影响另一个?
我猜它们是完全独立的,因为可以在事后创建索引并且 Spanner 将触发回填操作,该操作不会影响 Record
table 的运行状态.
写入索引的行为必须从节点获取一些资源,所以我想这确实是一个限制。在 Record
table 的高写入场景下,我们还将有效地为索引 table RecordByUser
调用第二次写入,消耗更多的节点写入吞吐能力。
因此添加到二级索引的行为不需要对源进行任何锁定 table(在本例中为 Record
)。主要关注的是写入吞吐量和这些写入的任何热点。例如,如果我们将时间戳记作为索引的第一部分进行索引,则对索引的写入会聚集在一起。我的理解对吗?
在现有 table 上创建索引的过程中,回填进程是否对索引持有独占锁,例如 Postgres:
https://www.postgresql.org/docs/current/index-locking.html
或者在回填发生时,新的写入可以在二级索引创建期间进入索引吗?
我可以想象一个在 spanners 端的回填过程,它拍摄一个读取快照并开始写入。给定 Spanners fancy clocks,如果它在索引中遇到比它试图写入的行更新的行,它只会将旧行丢弃在地板上并继续。
感谢提问。 Google 工程师在此寻求帮助。
+1 到 chainicko@ 通用锁定机制的答案。尽管回填仍然是 运行.
,但您仍然可以 read/write 原来的 table,因此它没有“锁定”Read/query 在回填期间不允许索引本身。但允许写入原始 table。新写入同时添加到索引中。回填后,Spanner 将确保在查询时只显示最新数据。
关于“在时间戳上建立索引作为索引的第一部分”的示例,由于它在索引上创建了一个热点,所以它仍然会对整个系统产生负面影响,即使它不会锁定原始 table.