Проблемы с производительностью при построении графа с транзакциями py2neo
Я пытаюсь построить полное двоичное дерево переменной глубины, используя py2neo. Я пытался использовать транзакции py2neo для отправки операторов create на сервер, но время выполнения ужасное.
Построение дерева с глубиной 8 (255 узлов) занимает около 16,7 секунд - подавляющее большинство этого времени затрачивается на фиксацию транзакции (если I Transaction.process() перед фиксацией, то обработка занимает большую часть времени выполнения). В чем может быть проблема? Каждый оператор cypher - это всего лишь одно Match и узел + отношение Create.
Вот функция, которая строит дерево
def buildBinaryTree(self):
depth = 1
tx = self.graph.begin()
g = self.graph
leaves = []
leaves.append("Root")
tx.run('CREATE(n {ruleName: "Root"})')
timeSum = 0
while depth < self.scale:
newLeaves = []
for leaf in leaves:
leftName = leaf + 'L'
rightName = leaf + 'R'
newLeaves.append(leftName)
newLeaves.append(rightName)
start = timer()
statement = ('MATCH(n {ruleName: "' + leaf + '"}) '
'WITH n CREATE (n)-[:`LINKS TO`]'
'->({ruleName: "' + leftName + '"})')
tx.run(statement)
statement = ('MATCH(n {ruleName: "' + leaf + '"}) '
'WITH n CREATE (n)-[:`LINKS TO`]'
'->(m {ruleName: "' + rightName + '"})')
tx.run(statement)
end = timer()
timeSum += (end - start)
leaves = newLeaves
depth += 1
print("Depth = " + str(depth))
print(timeSum)
start = timer()
print("Processing...")
tx.process()
print (timer() - start)
print("Committing...")
tx.commit()
print("Committed")
print (timer() - start)
И выход с масштабом = 8
building tree...
Depth = 2
Depth = 3
Depth = 4
Depth = 5
Depth = 6
Depth = 7
Depth = 8
0.009257960999775605
Processing...
16.753949095999815
Committing...
Committed
17.28687257200022
1 ответ
Попробуйте внести эти изменения, чтобы убедиться, что вы действительно работаете в одной транзакции и не откладываете излишнюю фиксацию обновлений:
- + Изменить
tx.run
вtx.append
, Это ставит в очередь каждое утверждение Cypher вместо немедленного его выполнения. - удалять
tx.process()
, поскольку у вас нет последующих операторов Cypher для постановки в очередь.
В идеале, вы также должны передавать параметры вместо того, чтобы модифицировать операторы Cypher каждый раз через цикл. Однако это не будет отвечать за медлительность, которую вы испытываете.