我有以下问题:我使用谷歌数据存储存储两种,公司和申请人,它们都来自不同的数据源,所以没有办法直接链接它们(没有共同的ID)。
我想要实现的是比较这两种实体的名称(在进行一些规范化之后),并将它们保存为类型为Match的新实体。
为此,我在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个实体/秒只是比我预期的要低得多。
谢谢
我可以想到一些可以优化您所做的事情的小技巧,例如:
如果c.dissolved != True(例如以is_potential = True开始,在迭代器中设置它为True,或者如果c.dissolved != True返回),而不是获取所有结果,迭代并快速退出
但是,理解数据模型和您试图实现的目标可能有助于提出更优的解决方案。一般来说,云数据存储不是为跨类型连接而设计,也许Google Cloud SQL更适合这个问题。
此外,数据增长预期也会有所帮助。到目前为止,将(10 + 1)百万条记录(或投影数据以节省空间)加载到内存中并执行内存连接这将是简单可行的,但显然不能扩展。
关于规模,如果每次匹配的公司键的数量太大而无法容纳在一个实体中,那么您当前的方法也可能存在问题。