分布式运算符可以跨多个服务器执行操作,而叶运算符、一元运算符、二元运算符或 n 元运算符则不能。
以下运算符为分布式运算符:
数据库架构
此页面上的查询和执行计划基于以下数据库架构:
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX),
BirthDate DATE
) PRIMARY KEY(SingerId);
CREATE INDEX SingersByFirstLastName ON Singers(FirstName, LastName);
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
MarketingBudget INT64
) PRIMARY KEY(SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
CREATE INDEX AlbumsByAlbumTitle ON Albums(AlbumTitle);
CREATE INDEX AlbumsByAlbumTitle2 ON Albums(AlbumTitle) STORING (MarketingBudget);
CREATE TABLE Songs (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
TrackId INT64 NOT NULL,
SongName STRING(MAX),
Duration INT64,
SongGenre STRING(25)
) PRIMARY KEY(SingerId, AlbumId, TrackId),
INTERLEAVE IN PARENT Albums ON DELETE CASCADE;
CREATE INDEX SongsBySingerAlbumSongNameDesc ON Songs(SingerId, AlbumId, SongName DESC), INTERLEAVE IN Albums;
CREATE INDEX SongsBySongName ON Songs(SongName);
CREATE TABLE Concerts (
VenueId INT64 NOT NULL,
SingerId INT64 NOT NULL,
ConcertDate DATE NOT NULL,
BeginTime TIMESTAMP,
EndTime TIMESTAMP,
TicketPrices ARRAY<INT64>
) PRIMARY KEY(VenueId, SingerId, ConcertDate);
您可以使用以下数据操纵语言 (DML) 语句向这些表中添加数据:
INSERT INTO Singers (SingerId, FirstName, LastName, BirthDate)
VALUES (1, "Marc", "Richards", "1970-09-03"),
(2, "Catalina", "Smith", "1990-08-17"),
(3, "Alice", "Trentor", "1991-10-02"),
(4, "Lea", "Martin", "1991-11-09"),
(5, "David", "Lomond", "1977-01-29");
INSERT INTO Albums (SingerId, AlbumId, AlbumTitle)
VALUES (1, 1, "Total Junk"),
(1, 2, "Go, Go, Go"),
(2, 1, "Green"),
(2, 2, "Forever Hold Your Peace"),
(2, 3, "Terrified"),
(3, 1, "Nothing To Do With Me"),
(4, 1, "Play");
INSERT INTO Songs (SingerId, AlbumId, TrackId, SongName, Duration, SongGenre)
VALUES (2, 1, 1, "Let's Get Back Together", 182, "COUNTRY"),
(2, 1, 2, "Starting Again", 156, "ROCK"),
(2, 1, 3, "I Knew You Were Magic", 294, "BLUES"),
(2, 1, 4, "42", 185, "CLASSICAL"),
(2, 1, 5, "Blue", 238, "BLUES"),
(2, 1, 6, "Nothing Is The Same", 303, "BLUES"),
(2, 1, 7, "The Second Time", 255, "ROCK"),
(2, 3, 1, "Fight Story", 194, "ROCK"),
(3, 1, 1, "Not About The Guitar", 278, "BLUES");
分布式联合运算符是派生出分布式交叉应用和分布式外部应用运算符的初始运算符。
在执行计划中,如果一个或多个局部分布式联合变体之上存在一个分布式联合变体,则该计划中会有分布式运算符。分布式联合变体执行子计划的远程分布。
局部分布式联合变体位于为查询执行的每个扫描之上。局部分布式联合变体可确保对于动态变化的分块边界,在发生重启时也能稳定执行查询。虽然此运算符在可视化方案中处于隐藏状态,但它始终存在。
分布式联合变体会尽可能使用分片谓词进行分片修剪。分片修剪是指远程服务器仅对满足谓词的分片执行子计划,从而缩短延迟时间并提高查询性能。
分布式联合
分布式联合运算符在概念上将一个或多个表分成多个分块,在每个分块上独立地远程计算子查询,然后联合所有结果。
以下查询演示了此运算符:
SELECT s.songname,
s.songgenre
FROM songs AS s
WHERE s.singerid = 2
AND s.songgenre = 'ROCK';
/*-----------------+-----------+
| SongName | SongGenre |
+-----------------+-----------+
| Starting Again | ROCK |
| The Second Time | ROCK |
| Fight Story | ROCK |
+-----------------+-----------*/
执行计划如下所示:

该分布式联合运算符向远程服务器发送子计划,远程服务器会对满足查询谓词 WHERE s.SingerId = 2 AND s.SongGenre = 'ROCK' 的分片执行表扫描。序列化结果运算符根据表扫描返回的行计算 SongName 和 SongGenre 值。然后,分布式联合运算符会返回来自远程服务器的组合结果作为 SQL 查询的结果。
属性和执行统计信息
运算符的属性描述了在执行运算符时使用的特征。执行统计信息是在查询执行期间收集的值,可帮助您评估运算符的性能。
分布式联合运算符具有其他不同的执行统计信息。属性
| 名称 | 说明 |
|---|---|
| 执行方法 | 在行执行中,运算符一次处理一行。 在批处理执行中,运算符一次处理一批行。 |
执行统计信息
| 名称 | 说明 |
|---|---|
| 本地并行执行次数 | 并行执行的子查询数量。 |
| 远程调用 | 执行的远程子查询的数量。 |
| 延迟时间 | 运算符中所有执行操作的耗时。 |
| 累计延迟时间 | 当前运算符及其后代的总时间。 |
| CPU 时间 | 执行运算符所花费的 CPU 时间总和。 |
| 累计 CPU 时间 | 执行相应运算符及其后代所花费的总 CPU 时间。 |
| 执行时间 | 运行查询和处理结果所花费的总时间。 |
| 返回的行数 | 相应运算符输出的行数 |
| 执行任务数量 | 相应运算符的执行次数。某些执行任务可以并行运行。 |
与交叉应用执行不同,一般情况下,执行是并行的。因此,分布式运算符的延迟时间是累积的,这与大多数运算符不同,后者会报告相应运算符增加的延迟时间。分布式并集下的执行次数取决于表的分界线,而分界线又取决于数据大小和负载,并且可能包含 use_additional_parallelism 语句提示。这种统计方法适用于所有分布式运算符。
分布式应用
分布式应用 (DA) 运算符通过在多个服务器上执行操作扩展了应用联接运算符。输入端会将行分组为批次(该运算符与常规的交叉应用运算符不同,后者一次只对一个输入行起作用)。DA 映射端是一组在远程服务器上执行的普通应用联接运算符。分布式应用联接支持与应用联接相同的应用方法。
属性和执行统计信息
运算符的属性描述了在执行运算符时使用的特征。执行统计信息是在查询执行期间收集的值,可帮助您评估运算符的性能。
分布式应用运算符具有其他不同的执行统计信息。属性
| 名称 | 说明 |
|---|---|
| 执行方法 | 在行执行中,运算符一次处理一行。 在批处理执行中,运算符一次处理一批行。 |
执行统计信息
| 名称 | 说明 |
|---|---|
| 本地并行执行次数 | 并行执行的子查询数量。 |
| 远程调用 | 执行的远程子查询的数量。 |
| 批次数 | 批次是同时处理的动态行集合。此指标显示了分布式交叉应用从输入端发送到 map 端的批次数。 |
| 延迟时间 | 运算符中所有执行操作的耗时。 |
| 累计延迟时间 | 当前运算符及其后代的总时间。 |
| CPU 时间 | 执行运算符所花费的 CPU 时间总和。 |
| 累计 CPU 时间 | 执行相应运算符及其后代所花费的总 CPU 时间。 |
| 执行时间 | 运行查询和处理结果所花费的总时间。 |
| 返回的行数 | 相应运算符输出的行数 |
| 执行任务数量 | 相应运算符的执行次数。某些执行任务可以并行运行。 |
分布式交叉应用
以下查询演示了此运算符:
SELECT albumtitle
FROM songs
JOIN albums
ON albums.albumid = songs.albumid;
/*-----------------------+
| AlbumTitle |
+-----------------------+
| Green |
| Nothing To Do With Me |
| Play |
| Total Junk |
| Green |
+-----------------------*/
执行计划如下所示:

DCA 输入包含对 SongsBySingerAlbumSongNameDesc 索引进行的索引扫描,该索引会批处理 AlbumId 的行。 DCA 的映射端是标准交叉应用,其中输入是一批行,映射端是对索引 AlbumsByAlbumTitle 的索引扫描,受与 AlbumsByAlbumTitle 索引中的 AlbumId 键匹配的输入行中 AlbumId 谓词的限制。映射会返回与批处理输入行中的 SingerId 值相对应的 SongName。
此示例的 DCA 过程总结如下:DCA 的输入是来自 Albums 表的批处理行,而 DCA 的输出是将这些行应用于索引扫描的映射。
分布式外部应用
分布式外部应用是一种具有左外联接语义的 DA。如需了解语义的详细信息,请参阅外部应用。
以下查询演示了此运算符:
SELECT lastname,
concertdate
FROM singers LEFT OUTER join@{JOIN_TYPE=APPLY_JOIN} concerts
ON singers.singerid=concerts.singerid;
/*----------+-------------+
| LastName | ConcertDate |
+----------+-------------+
| Trentor | 2014-02-18 |
| Smith | 2011-09-03 |
| Smith | 2010-06-06 |
| Lomond | 2005-04-30 |
| Martin | 2015-11-04 |
| Richards | |
+----------+-------------*/
执行计划如下所示:

分布式半应用
分布式半应用是一种具有半联接语义的 DA。如需详细了解语义,请参阅 semi apply。
分布式反半联接
分布式反半联接应用是一种具有反半联接语义的 DA。如需详细了解语义,请参阅 anti-semi apply。
分布式合并联合
分布式合并联合运算符在多个远程服务器间分布查询。然后,它会合并查询结果以生成经过排序的结果(称为分布式合并排序)。
分布式合并联合执行以下步骤:
根服务器会将子查询发送到托管所查询数据的分块的每个远程服务器。子查询包含用于按特定顺序对结果进行排序的指令。
每个远程服务器对其分块执行子查询,然后按请求的顺序发送回结果。
根服务器合并经过排序的子查询,以生成完全排序的结果。
对于 Spanner 版本 3 及更高版本,分布式合并联合默认处于启用状态。
属性和执行统计信息
运算符的属性描述了在执行运算符时使用的特征。执行统计信息是在查询执行期间收集的值,可帮助您评估运算符的性能。
分布式应用运算符具有其他不同的执行统计信息。属性
| 名称 | 说明 |
|---|---|
| 执行方法 | 在行执行中,运算符一次处理一行。 在批处理执行中,运算符一次处理一批行。 |
执行统计信息
| 名称 | 说明 |
|---|---|
| 本地并行执行次数 | 并行执行的子查询数量。 |
| 远程调用 | 执行的远程子查询的数量。 |
| 批次数 | 批次是同时处理的动态行集合。此指标显示了分布式交叉应用从输入端发送到 map 端的批次数。 |
| 延迟时间 | 运算符中所有执行操作的耗时。 |
| 累计延迟时间 | 当前运算符及其后代的总时间。 |
| CPU 时间 | 执行运算符所花费的 CPU 时间总和。 |
| 累计 CPU 时间 | 执行相应运算符及其后代所花费的总 CPU 时间。 |
| 执行时间 | 运行查询和处理结果所花费的总时间。 |
| 返回的行数 | 相应运算符输出的行数 |
| 执行任务数量 | 相应运算符的执行次数。某些执行任务可以并行运行。 |
推送广播哈希联接
推送广播哈希联接运算符是基于分布式哈希联接的 SQL 联接实现。推送广播哈希联接运算符从输入端读取行,以构建一批数据。该运算符会将该批数据广播到包含映射端数据的所有服务器。在接收该批数据的目标服务器上,该运算符使用该批数据作为构建端数据来构建哈希联接,并将本地数据作为哈希联接的探测端进行扫描。
推送广播哈希联接具有以下优势:
- 如果 build 表较小,则可以将其发送到所有 map 端拆分。
- 可以扫描地图端表,无论是否带有剩余过滤条件。当联接键与映射表的主键不相同时,就会出现这种情况。
优化器不会自动选择推送广播哈希联接。如需使用此运算符,请在查询提示上将联接方法设置为 PUSH_BROADCAST_HASH_JOIN,如以下示例所示:
SELECT a.albumtitle,
s.songname
FROM albums AS a join@{join_method=push_broadcast_hash_join} songs AS s
ON a.singerid = s.singerid
AND a.albumid = s.albumid;
/*-----------------------+--------------------------+
| AlbumTitle | SongName |
+-----------------------+--------------------------+
| Green | The Second Time |
| Green | Starting Again |
| Green | Nothing Is The Same |
| Green | Let's Get Back Together |
| Green | I Knew You Were Magic |
| Green | Blue |
| Green | 42 |
| Terrified | Fight Story |
| Nothing To Do With Me | Not About The Guitar |
+-----------------------+--------------------------*/
执行计划如下所示:

推送广播哈希联接的输入是 AlbumsByAlbumTitle 索引。该运算符会将相应输入序列化为一批数据。该运算符会将相应批次发送到索引 SongsBySingerAlbumSongNameDesc 的所有本地分块,并在其中对该批次进行反序列化并将其构建到哈希表中。然后,哈希表会将本地索引数据用作返回匹配结果的探测。
在返回之前,生成的匹配项也可能会根据残余条件进行过滤。(例如,非等值联接中会出现残余条件。)
属性和执行统计信息
运算符的属性描述了在执行运算符时使用的特征。执行统计信息是在查询执行期间收集的值,可帮助您评估运算符的性能。
分布式应用运算符具有其他不同的执行统计信息。属性
| 名称 | 说明 |
|---|---|
| 执行方法 | 在行执行中,运算符一次处理一行。 在批处理执行中,运算符一次处理一批行。 |
执行统计信息
| 名称 | 说明 |
|---|---|
| 本地并行执行次数 | 并行执行的子查询数量。 |
| 远程调用 | 执行的远程子查询的数量。 |
| 批次数 | 批次是同时处理的动态行集合。此指标显示了分布式交叉应用从输入端发送到 map 端的批次数。 |
| 延迟时间 | 运算符中所有执行操作的耗时。 |
| 累计延迟时间 | 当前运算符及其后代的总时间。 |
| CPU 时间 | 执行运算符所花费的 CPU 时间总和。 |
| 累计 CPU 时间 | 执行相应运算符及其后代所花费的总 CPU 时间。 |
| 执行时间 | 运行查询和处理结果所花费的总时间。 |
| 返回的行数 | 相应运算符输出的行数 |
| 执行任务数量 | 相应运算符的执行次数。某些执行任务可以并行运行。 |