Python 如何优化在“django mptt”中添加新节点?

Python 如何优化在“django mptt”中添加新节点?,python,database,django,performance,django-mptt,Python,Database,Django,Performance,Django Mptt,我正在创建一个脚本,它将同步两个数据库。数据库中有一个数据应该存储为树,因此我将其用于新的数据库。当我同步数据库时,我从旧数据库中选择新数据,并将其保存在新数据库中 我想知道是否有更好的方法将新节点添加到树中?现在看来是下一步: ... # Add new data to DB for new_record in new_records: # Find appropriate parent using data in 'new_record' parent = get_paren

我正在创建一个脚本,它将同步两个数据库。数据库中有一个数据应该存储为树,因此我将其用于新的数据库。当我同步数据库时,我从旧数据库中选择新数据,并将其保存在新数据库中

我想知道是否有更好的方法将新节点添加到树中?现在看来是下一步:

...
# Add new data to DB
for new_record in new_records:
    # Find appropriate parent using data in 'new_record'
    parent = get_parent(new_record)

    # Create object which should be added using data in 'new_record'
    new_node = MyMPTTModel(...)
    new_node.insert_at(parent, save = True)
    # Similar to:
    # new_node.insert_at(parent, save = False)
    # new_node.save()
但是它工作得很慢。我认为它是这样工作的,因为在每次调用
insert_at(…,save=True)
方法
django-mptt
后,应该将新节点写入数据库,并修改数据库中已有记录的
left
right

有没有办法在每次调用
insert_at
时修改查询,然后在调用
save
时将所有更改一起应用?或者您知道如何减少执行时间的其他方法吗


提前感谢。

Django MPTT为您维护一个树结构。因此,在的每个
insert\u处,它都会修改插入节点右侧的所有节点-这就是您遇到性能问题的原因

一种方法是在不使用
django-mptt
的情况下手动构建树结构

因此,您必须获取新记录,并根据这些记录,计算出必须修改树中的旧节点的方式。由于您只是在插入数据,所以只有左属性和右属性将发生更改,而不是级别,所以这应该会使更改更容易一些。一旦您知道要修改哪些节点,就可以使用一个
update
事务(编辑)来修改它们

然后,您可以开始插入新数据。同样,最快的方法是计算每个新条目的左、右和级别值,然后执行一次
bulk\u insert
(Django>=1.4)。这样做只会导致两个db操作,显然在db事务方面应该快得多

但是,这种方法需要一些智能的方法来确定如何更改树中的旧节点。最简单的方法是将所有树转储到python结构中,然后找出该结构上的更改。然而,如果由于内存限制,您的树非常大,那么这将是不可行的

目前还不确定是否有更有效的方法。也许StackOverflow上的其他人有一些很酷的想法

编辑


对于
更新
的混乱表示抱歉。我是说一笔交易。在这种情况下,我通常执行原始sql查询,其中我执行
更新tbname集。。。其中id=1;更新tbname集。。。其中id=2首先,不要在
处使用
insert\u。这不是性能缓慢的原因,但这是不必要的,而且看起来很难看。只需设置节点。父节点

for new_record in new_records:
    new_node = MyMPTTModel(..., parent=get_parent(new_record))
    new_node.save()
现在是性能问题。如果您使用的是最新的mptt(git master,而不是0.5.4),则会调用一个上下文管理器,以防止mptt在添加所有节点之前执行大量更新:

with transaction.atomic():
    with MyMPTTModel.objects.delay_mptt_updates():
        for new_record in new_records:
            new_node = MyMPTTModel(..., parent=get_parent(new_record))
            new_node.save()
或者,如果您几乎接触到整个树,您可以通过使用并在最后重建整个树来加快速度:

with transaction.atomic():
    with MyMPTTModel.objects.disable_mptt_updates():
        for new_record in new_records:
            new_node = MyMPTTModel(..., parent=get_parent(new_record))
            new_node.save()
    MyMPTTModel.objects.rebuild()

如何仅使用一条
update
语句修改整个分支?@craigds-当使用新的父节点更新现有节点时,这是否有效?在最近的MPTT中,我尝试了使用这两种上下文管理器,但即使在重建之后,它似乎也不起作用。