在 RethinkDB 中获取两个流差异的有效方法
Efficient way to get difference of two streams in RethinkDB
我是 运行 RethinkDB 的一些性能基准(与特定用例相关)。在我的模拟中,有 2 个 table:contact
和 event
。一个联系人有很多事件。事件 table 有 2 个索引:contact_id 和 [campaign_id, node_id, event_type]
上的复合索引。 contact
table 在 event
table.
中有大约 50 万个联系人和大约 175 万个文档
我遇到的问题是查找所有拥有 sent
event_type 但没有 open
event_type 的联系人。以下是我开始工作的查询:
r.table("events").
get_all([1, 5, 'sent'], {index: 'campaign'})['contact_id'].distinct
.set_difference
(r.table("events").get_all([1, 5, 'open'], {index: 'campaign'})['contact_id'].distinct)
.count.run(conn)
但是这个查询使用的是set difference,不是stream difference。我也尝试过使用 difference operator:
r.table("events").
get_all([1, 5, 'sent'], {index: 'campaign'})['contact_id'] .difference
(r.table("events").get_all([1, 5, 'open'], {index: 'campaign'})['contact_id'])
.count.run(conn)
这个查询永远不会完成,奇怪的是即使在我看到(在 RethinkDB 仪表板中)中止查询后,读取也不会停止。
执行此类查询的最有效方法是什么?
跟进:找到所有 sent
event_type 但没有 open
event_type 的男性联系人。我现在拥有的是:
r.table("contacts").get_all(r.args(
r.table("events").get_all([1, 5, 'sent'], {index: 'campaign'})['contact_id'].distinct
.set_difference
(r.table("events").get_all([1, 5, 'open'], {index: 'campaign'})['contact_id'].distinct)))
.filter({gender: 1}).count.run(conn)
提高效率的一种方法是对数据进行非规范化。不用单独的 contact
和 event
table,只需 contact
table 并使每个 contact
都有一个事件数组。然后你可以写:
r.table('contacts').indexCreate('sent_but_not_open', function(row) {
return row('events').contains('sent').and(
row('events').contains('open').not());
});
如果每个联系人的事件数量很少,那将很有效。如果每个联系人有数千或数百万个事件,它就会崩溃。
RethinkDB 不提供在服务器上延迟区分两个流的方法。您可以做的最好的事情是将复合索引更改为 [campaign_id, node_id, event_type, contact_id]
,将 get_all([1, 5, 'sent'], {index: 'campaign'})
替换为 .between([1, 5, 'sent', r.minval], [1, 5, 'sent', r.maxval
], {index: 'campaign'})and then put
.distinct({index: 'campaign'})['contact_id']on the end. That will give you a stream of distinct contact IDs rather than an array, and these contact IDs will be sorted. You can then do the same for the
open` 事件,并通过执行类似合并排序的操作来区分客户端中的两个有序流。
我是 运行 RethinkDB 的一些性能基准(与特定用例相关)。在我的模拟中,有 2 个 table:contact
和 event
。一个联系人有很多事件。事件 table 有 2 个索引:contact_id 和 [campaign_id, node_id, event_type]
上的复合索引。 contact
table 在 event
table.
我遇到的问题是查找所有拥有 sent
event_type 但没有 open
event_type 的联系人。以下是我开始工作的查询:
r.table("events").
get_all([1, 5, 'sent'], {index: 'campaign'})['contact_id'].distinct
.set_difference
(r.table("events").get_all([1, 5, 'open'], {index: 'campaign'})['contact_id'].distinct)
.count.run(conn)
但是这个查询使用的是set difference,不是stream difference。我也尝试过使用 difference operator:
r.table("events").
get_all([1, 5, 'sent'], {index: 'campaign'})['contact_id'] .difference
(r.table("events").get_all([1, 5, 'open'], {index: 'campaign'})['contact_id'])
.count.run(conn)
这个查询永远不会完成,奇怪的是即使在我看到(在 RethinkDB 仪表板中)中止查询后,读取也不会停止。
执行此类查询的最有效方法是什么?
跟进:找到所有 sent
event_type 但没有 open
event_type 的男性联系人。我现在拥有的是:
r.table("contacts").get_all(r.args(
r.table("events").get_all([1, 5, 'sent'], {index: 'campaign'})['contact_id'].distinct
.set_difference
(r.table("events").get_all([1, 5, 'open'], {index: 'campaign'})['contact_id'].distinct)))
.filter({gender: 1}).count.run(conn)
提高效率的一种方法是对数据进行非规范化。不用单独的 contact
和 event
table,只需 contact
table 并使每个 contact
都有一个事件数组。然后你可以写:
r.table('contacts').indexCreate('sent_but_not_open', function(row) {
return row('events').contains('sent').and(
row('events').contains('open').not());
});
如果每个联系人的事件数量很少,那将很有效。如果每个联系人有数千或数百万个事件,它就会崩溃。
RethinkDB 不提供在服务器上延迟区分两个流的方法。您可以做的最好的事情是将复合索引更改为 [campaign_id, node_id, event_type, contact_id]
,将 get_all([1, 5, 'sent'], {index: 'campaign'})
替换为 .between([1, 5, 'sent', r.minval], [1, 5, 'sent', r.maxval
], {index: 'campaign'})and then put
.distinct({index: 'campaign'})['contact_id']on the end. That will give you a stream of distinct contact IDs rather than an array, and these contact IDs will be sorted. You can then do the same for the
open` 事件,并通过执行类似合并排序的操作来区分客户端中的两个有序流。