echoface/be_indexer

这块实时计算的逻辑是否可以更加高效?

Closed this issue · 10 comments

func (h *DefaultEntriesHolder) GetEntries(field *FieldDesc, assigns Values) (r EntriesCursors, e error) {

1.多值查询(A or B)中,对同一个属性下面的多个key有多个entries。这些entries需要取并集,并重新排序。
如果entries已经有序,在合并时通过n 有序列表合并的方式会更加高效。
2.此外多值查询可能不止是A or B,可能是 A and B。是否需要提供一个多个entries取并集的场景

不好意思, 最近在忙其他事情, 没有关注到这个问题.
A1.
按照论文的描述: 对于一个DNF 中一个Conjunction 的描述: {tag in/not in [v1, v2, v3]} 指tag 需要满足 v1,v2,v3 中任意一个(这里暂时假设成in逻辑). 那么对于一个文档: doc 它的tag属性是: v2, v11; 对于布尔表达式{tag in [v1, v2, v3]} 显然是满足的. 目前多值查询上, 是构造了多个访问posting list(entries) 的cursor. 并在skip[to]过程中按照排序的形式进行的,所以并不需要在retrieve 时做entries sort的操作, 具体可以参考FieldCursor部分
A2.
对于你这里说的查询A or B . 我理解这里描述的A,B 是指维度field. A or B 的场景会在构建索引的时候拆分出两个Conjunction, 也就是说会将逻辑描述按照标准的DNF范式组织起来(即: 同一个Conjunction 内不同Field 都是And的逻辑关系, OR的关系则在DNF的要求下拆分成独立的Conjunction, 同一个文档不同Conjunction之间是或的逻辑) 对于查询,只需要提供Assign的属性即可, 并没有and/or的逻辑概念. 举个例子

doc 1: [
      {(age  in [18-30], gender not in [男])}, // Conjunction 1: 18-30岁 且 不是男性
      {(tag in [X粉丝团])}                                // Conjunction 2: X粉丝群
      // Conjunction 之间为**或**的逻辑. 理解了DNF这种标准形式, 那么对于一个索引查询是否匹配也就很好理解了  
]

当一个流量有: ‘X粉丝团’ 就会命中doc1.Conjunction2 或者 用户age: 25, 性别: 未知 则会命中doc1.Conjunction1 这两种情况下都会查询到布尔文档doc1.

这里有一点需要关注的是,这个库实现的是布尔索引而非通用数据索引(ES). 背后的原理和技术有很多相似的地方, 但是在理解的形式上会有一些差别

如果conjid与 docid相关的话,如果两个doc的conj完全相同,conjid还是有可能不同吗?

另外好像没看到delet doc 或者 update操作。增量索引应该怎么做呀 0-0

如果conjid与 docid相关的话,如果两个doc的conj完全相同,conjid还是有可能不同吗?

会不同, 可以看下conjunction id的生成逻辑, 可以简单的理解成conjctionid= docid << 48 | index | conj_size

另外好像没看到delet doc 或者 update操作。增量索引应该怎么做呀 0-0

这个逻辑更像是工程上使用这个库如何put/del/mod document,和其他大部分其他索引构建相似,一般都是使用定时构建。配合工程上的其他模块(eg: 分布式存储) 合理的将文档分布在不同机器上。 做分布式索引查询; 其他使用上的交流能微信交流吗: 添加微信:SuperHgO

这里也有同样疑问,索引的更新涉及到全量和增量,put/del/mod document 会涉及到索引的修改,如果不实现的话,这里的意图是要每次全量构建索引吗?

这里也有同样疑问,索引的更新涉及到全量和增量,put/del/mod document 会涉及到索引的修改,如果不实现的话,这里的意图是要每次全量构建索引吗?

如果将索引作为一个服务,当广告的定向被修改后。业务将其转化成布尔文档后发布到索引服务(假设成es),索引服务按照其固定的策略重构索引数据,从生效时效和功能上评估并没有什么问题;其不能像关系型数据库索引一样实时更新与其逻辑关系有关,并不是简单多键值索引。在做好分片后,索引数据的构建速度应该并无什么明显问题,因为文档是逻辑完整的从一个版本换到另一个版本。从接触到的广告系统来看,定向只是最基础的部分,后面还有一些列的反馈控制和其他非布尔逻辑过滤,从而最终得到召回的广告

这里也有同样疑问,索引的更新涉及到全量和增量,put/del/mod document 会涉及到索引的修改,如果不实现的话,这里的意图是要每次全量构建索引吗?

如果将索引作为一个服务,当广告的定向被修改后。业务将其转化成布尔文档后发布到索引服务(假设成es),索引服务按照其固定的策略重构索引数据,从生效时效和功能上评估并没有什么问题;其不能像关系型数据库索引一样实时更新与其逻辑关系有关,并不是简单多键值索引。在做好分片后,索引数据的构建速度应该并无什么明显问题,因为文档是逻辑完整的从一个版本换到另一个版本。从接触到的广告系统来看,定向只是最基础的部分,后面还有一些列的反馈控制和其他非布尔逻辑过滤,从而最终得到召回的广告

我理解索引的更新会是一个复杂的过程。如你所说,如果采用分片方式提升构建效率,那这里对索引分片的策略有什么好方法呢?比如5分钟产生了ad1,ad2 .... adn,那么如果简单哈希策略可能会涉及到多个极端n个分片的重建,这一般也是不能接受的吧

这里也有同样疑问,索引的更新涉及到全量和增量,put/del/mod document 会涉及到索引的修改,如果不实现的话,这里的意图是要每次全量构建索引吗?

如果将索引作为一个服务,当广告的定向被修改后。业务将其转化成布尔文档后发布到索引服务(假设成es),索引服务按照其固定的策略重构索引数据,从生效时效和功能上评估并没有什么问题;其不能像关系型数据库索引一样实时更新与其逻辑关系有关,并不是简单多键值索引。在做好分片后,索引数据的构建速度应该并无什么明显问题,因为文档是逻辑完整的从一个版本换到另一个版本。从接触到的广告系统来看,定向只是最基础的部分,后面还有一些列的反馈控制和其他非布尔逻辑过滤,从而最终得到召回的广告

我理解索引的更新会是一个复杂的过程。如你所说,如果采用分片方式提升构建效率,那这里对索引分片的策略有什么好方法呢?比如5分钟产生了ad1,ad2 .... adn,那么如果简单哈希策略可能会涉及到多个极端n个分片的重建,这一般也是不能接受的吧

索引更新如果不做任何优化,就是划分的一个分片上所有文档的一次遍历, tokenize, entries sort 操作,存在CPU,内存的消耗,前两个步骤是可以优化的,做到只需要对有更新的文档进行。但是最后的entries合并与sort则没那么方便优化;第二个问题分片策略 一般采用分槽方式,文档不多时eg:几十万级,那就一个就够了,如果发现性能那个,CPU,内存存在瓶颈,那就对半分,再增长到千万级,那就再对照对半分的方式处理,当然也有其他管理调度的形式

目前top级公司一个业务在投放的计划(文档)也就千万级;再多可能在业务划分上就是两套系统甚至多个了eg:电商部分,品牌广告....等;索引基本上是为了极致的查询而优化的,目前对于常见的几种布尔文档索引的论文,目前没有了解到相关论文有在索引修改更新方面的结构优化,很早之前有见过基于树结构能够支持文档更新,但是那个是将一个文档作为逻辑整体的,算不上对“值”的索引,这方面@showntop 有可以提供参考的吗?