使用Google AppEngine MapReduce匹配实体

时间:2016-09-27 17:41:23

标签: python google-app-engine mapreduce google-cloud-datastore

我遇到以下问题:我使用Google Datastore存储两种类型,公司申请人,它们都来自不同的数据源,所以没有办法直接链接它们(没有共同的ID)。

我想要实现的是比较这两种实体的名称(在做一些规范化之后)并将它们保存为匹配

为此我在appengine上创建了一个MapReduce作业,遍历所有申请人(约1M个实体),并为每个实体查询具有相同名称的公司(总共约10M个实体),但这个过程非常缓慢,我我得到以下吞吐量:

mapper-calls:691411(9.27 / sec avg。)
mapper-walltime-ms:1724026200(23108.41 / sec avg。)

墙上的时间对我来说有点太高了,但我不确定它的意思,我正在运行32个分片,代码如下:

def match_map(applicant):        
    if(applicant.applicant_name_normalised != ""):
        # Check against the companies
        cps = Company.query(Company.name_normalised == applicant.applicant_name_normalised).fetch(projection=[Company.dissolved])
        if(len(cps) > 0):
            is_potential = True
        else:
            return

        m = Match(id=applicant.key.id())
        idList = []

        for c in cps:
            idList.append(c.key)
            if(c.dissolved != True):
                is_potential = False

        m.companies = idList
        m.applicant = applicant.key
        m.is_potential = is_potential
        if(is_potential):
            yield op.db.Put(m)
    idList[:] = []

我怎样才能实现这一点,以便它运行得更快?我几乎要离开谷歌数据存储区并在另一个数据库或使用脚本上执行此操作,我知道查询可能很昂贵但是10个实体/ s的速度比我预期的低得多。

由于

1 个答案:

答案 0 :(得分:1)

我可以想到可以优化您所做的事情的小技巧,例如:

如果c.dissolved!= True(例如以is_potential = True开头,在迭代器中将其设置为True,或者如果c.dissolved!= True则返回),而不是获取所有结果,快速迭代和保释。

但是,了解数据模型以及您要实现的目标可能有助于提出更优化的解决方案。通常,Cloud Datastore不是 专为交叉种类加入而设计,也许谷歌云SQL更适合这个问题。

此外,数据增长预期将有所帮助。截至目前,将(10 + 1)百万条记录(或预计数据以节省空间)加载到内存中并进行内存中连接 这将是简单而可行的,但显然无法扩展。

关于规模,如果每个匹配的公司密钥数量大到适合一个实体,那么您当前的方法也可能会出现问题。