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所以我在一个sql查询中执行多个sql语句。根据我的经验,db的昂贵部分不是执行语句,而是事务本身,因为存在网络延迟、db锁等。因此,拥有一个事务可以让db尽可能快。但是,不确定如何在django中使用QuerySet实现这一点。我通常进行原始sql查询。首先,不要在
处使用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中,我尝试了使用这两种上下文管理器,但即使在重建之后,它似乎也不起作用。