【发布时间】:2016-03-29 23:23:46
【问题描述】:
我最近一直在研究 RethinkDB,很害怕看到加入文档部分。据我所知,RethinkDB 将数据存储在分片中,这些分片可能是分布式的(这对于连接来说实际上是一个巨大的NO)。那么 RethinkDB 是如何进行连接查询的呢?它基本上是在一个节点上下载所有数据(这会使现有索引变得无用,不是吗?),还是使用更复杂的算法?
【问题讨论】:
我最近一直在研究 RethinkDB,很害怕看到加入文档部分。据我所知,RethinkDB 将数据存储在分片中,这些分片可能是分布式的(这对于连接来说实际上是一个巨大的NO)。那么 RethinkDB 是如何进行连接查询的呢?它基本上是在一个节点上下载所有数据(这会使现有索引变得无用,不是吗?),还是使用更复杂的算法?
【问题讨论】:
在 RethinkDB 2.2 及之前版本中,eqJoin 对左侧输入中的每个文档在右侧表上执行索引 getAll 操作。
此操作在托管eqJoin 命令左侧输入的每个分片上启动。
正如您所指出的,执行getAll 可能需要通过网络到达另一台服务器上右侧表的分片。但是索引仍在使用中。
(你可以在这里找到eqJoin的实现:https://github.com/rethinkdb/rethinkdb/blob/v2.2.x/src/rdb_protocol/terms/rewrites.cc#L121只是对其他操作的重写)
从即将推出的 RethinkDB 2.3 开始,eqJoin 使用批处理的 getAll 操作。这意味着它从左侧输入读取一堆结果(例如,最多 1 MB),然后向右侧表的分片发出一个 getAll。一旦从这些分片中取回数据,它就会将其与之前从左侧输入读取的数据结合起来,并将其传递给用户。然后重复此操作,直到左侧输入的所有数据都已处理完毕。
这种方法需要的服务器之间的网络往返次数要少得多,而且通常要快得多。您可以在 https://github.com/rethinkdb/rethinkdb/issues/5115 找到有关新实现的更多详细信息。
最后,其他可用的连接操作(innerJoin 和 outerJoin)没有被编入索引,并且不应该用于任何显着大小的数据集,正如文档还指出的那样。
【讨论】: