Import großer Datenmengen

Um im Open Source ERP System Odoo mit Ihren bisherigen Alt-Daten aus einem anderen System oder einer älteren Odoo Version arbeiten zu können, müssen diese Daten zunächst in Ihr neues Odoo System importiert werden. In vielen Dokumentationen wird hier ausschließlich von der Möglichkeit über die create Methode (Insert) oder der write Methode (Update) berichtet. 

Werden jetzt größere Datenmengen importiert, so fällt auf, dass der Import unter Berücksichtigung der Datenmenge sehr lange dauern kann. Wodurch wir uns die Frage gestellt haben, ob es hier nicht eine schnellere Alternative gibt. Diese Alternative ist die sogenannte load-Methode und wird sowohl für einen Insert als auch für ein Update genutzt. Der nachfolgende Artikel soll verdeutlichen, um wie viel schneller die Anwendung der load-Methode gegenüber der create-/write-Methode ist.

Für unsere Tests wird die Faker Bibliothek von Python verwendet, um zufällige Unternehmensdaten im Bereich res.partner zu generieren (https://github.com/joke2k/faker). Hier muss gesagt werden, dass der Einfachheit wegen ausschließlich der name-Parameter eines res.partner Datensatzes gesetzt wird.

Nachfolgend zwei Python Skripte, einmal auf Basis der create-Methode und einmal auf Basis der load-Methode.

create:

# -*- coding: UTF-8 -*-
##############################################################################
#
#    Python Script for Odoo, Open Source Management Solution
#    Copyright (C) 2014-now Equitania Software GmbH(<http://www.equitania.de>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import xmlrpclib
from faker import Faker
import time

username = "admin"
pwd = "pw"
dbname = "dbname"
baseurl = "http://localhost:8069"

sock_common = xmlrpclib.ServerProxy(baseurl + "/xmlrpc/common")

uid = sock_common.login(dbname, username, pwd)

sock = xmlrpclib.ServerProxy(baseurl + "/xmlrpc/object")

start_time = time.time()

_totalcount = 1000
fake = Faker('de_DE')
for i in range(_totalcount):
    name = fake.company()
    values = {
        'name': name
    }

    sock.execute(dbname, uid, pwd, 'res.partner', 'create', values)

# Store end time
end_time = time.time()

# Calculate the execution time and print the result
print("%.10f seconds" % (end_time - start_time))

print 'Fertig'

load:

# -*- coding: UTF-8 -*-
##############################################################################
#
#    Python Script for Odoo, Open Source Management Solution
#    Copyright (C) 2014-now Equitania Software GmbH(<http://www.equitania.de>).
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
import xmlrpclib
from faker import Faker
import time

username = "admin"
pwd = "pw"
dbname = "dbname"
baseurl = "http://localhost:8069"

sock_common = xmlrpclib.ServerProxy(baseurl + "/xmlrpc/common")

uid = sock_common.login(dbname, username, pwd)

sock = xmlrpclib.ServerProxy(baseurl + "/xmlrpc/object")

name_list = []
i = 1

start_time = time.time()

_totalcount = 1000
fake = Faker('de_DE')
for i in range(_totalcount):
    name = fake.company()
    external_id = 'import.res_partner' + str(i)
    new_name_list = [external_id, name]
    name_list.append(new_name_list)

print"name_list: ", name_list


sock.execute(dbname, uid, pwd, 'res.partner', 'load', ['id', 'name'], name_list, {'context': {}})

# Store end time
end_time = time.time()

# Calculate the execution time and print the result
print("%.10f seconds" % (end_time - start_time))

# sock.execute(dbname, uid, pwd, 'res.partner', 'load', ['id','name'],
#     [
#     #Update
#     [external_id,'Testpartner_1'],
#     #Insert
#      ['my_partner.external_id2','Testpartner_2'],
#     ]
#     , {'context': {}})


print 'Fertig!'

Nach dem durchgeführten Import sieht man nach der Ausführung des nachfolgenden SQL-Statements:

Select * From ir_model_data where model='res.partner'

einen Auschnitt der erstellten Datensätze in dem Datenmodell 'ir.model.data'. Hier ist auch zu erkennen, wie die externe ID zusammengesetzt (module.name der Tabelle 'ir.model.data') wird. 

Datensätze

res.partner

1001001000
create22,53 sec25,28 sec251,84 sec
load15,68 sec15,63 sec169,71 sec
Performancegewinn~ 30,4 %~ 38,2 %~ 32,6 %

Diese Tabelle zeigt die Ergebnisse unseres kleinen Tests. Es ist klar zu sehen, dass durch die load-Methode ein Performancegewinn von ~ 34 % möglich ist.

Zusammenfassend lässt sich sagen, dass durch die Verwendnung der load-Methode der Performancegewinn beachtlich ist. So kommen wir zu dem Ergebnis, dass gerade bei großen Importdatenmengen nicht auf die Verwendung der load-Methode verzichtet werden sollte.