Mejorando la performance de la importación de datos en Odoo

Gustavo Orrillo
- 27/06/2020 - 1 min. de lectura


Trabajando para un cliente me vi en la necesidad de importar el padrón de AGIP el cual cuenta con centenares de miles de registros. En un primer momento lo importé con XMLRPC, y si bien es una buena idea, tiene algunos problemas de performance debido a que va por el ORM y ademas por cada registro hace un commit. Lo cual genera la demora de horas en el procesamiento.

Probe con una herramienta interesante, odoo_csv_import la cual parece prometedora pero me tope con un pequeño problemita en el principio y decidí desarrollar mi propio script. Basicamente hice un script con python y psycopg2 que hacía el commit cada 1,000 registros. Y bajó los tiempos de más de cinco horas, a unos 30 minutos. Calculo que si el commit lo hacía cada 5,000 registros los tiempos iban a bajar más. Pero bueno, la idea era probar otro approach para bajar los tiempos de carga y hacerlos manejables. 

Un punto en el que hay que tener especial cuidado es, el registro a insertar debe ser identico al registro que inserta Odoo. Es por ello que le deben agregar la información de los campos id, create_uid, write_uid, write_date y create_date. Pero haganlo con mucho cuidado y testeen bien, porque si manejando la base de datos de Odoo con SQL se equivocan, la unica manera que funcione de vuelta es restaurando el backup.

Así que, si quieren conocer el script a modo de ejemplo, el mismo se encuentra debajo:

#!/usr/bin/python
import csv
import psycopg2
from datetime import datetime
try:
    conn = psycopg2.connect("dbname='testdb' user='odoo' host='localhost' password='superodoo'")
except:
    print "I am unable to connect to the database"
    import pdb;pdb.set_trace()
cur = conn.cursor()
cur_insert = conn.cursor()
cur.execute("""SELECT max(id) from account_padron""")
rows = cur.fetchall()
max_id = rows[0][0] + 1
f = open('ARDJU008042020.csv','rt')
csv_reader = csv.reader(f,delimiter=';')
cur_insert.execute('begin transaction')
for i,row in enumerate(csv_reader):
    print i,max_id + i,max_id,row
    dt_now = str(datetime.now())
    id = max_id +i
    cuit = row[3]
    date_from = str(datetime.strptime(row[1],'%d%m%Y').date())
    date_to = str(datetime.strptime(row[2],'%d%m%Y').date())
    create_uid = 2
    write_uid = 2
    percent = float(row[7].replace(',','.'))
    tax = 'RET_IIBB_AGIP'
    sql = "insert into account_padron(id,cuit,date_from,date_to,percent,tax,create_uid,write_uid,create_date,write_date) values (%s,'%s','%s','%s',%s,'%s',2,2,'%s','%s')"\            % (id,cuit,date_from,date_to,percent,tax,dt_now,dt_now)
    cur_insert.execute(sql)
    if i % 1000:
        cur_insert.execute('commit')
cur_insert.execute('commit')
cur.close()
cur_insert.close()


Acerca de:

Gustavo Orrillo

Passionate about programming, he has implemented Odoo for different types of businesses since 2010. In Moldeo Interactive he is a founding Partner and Programmer; In addition to writing on the Blog about different topics related to the developments he makes.