@file2
improving further

Как увеличить скорость записи в базу при парсинге XML файла?

Сделал программку которая парсит XML файлы и записывает данные в базу Oracle.
Проблема в том что запись в базу происходит очень медленно. Как я понял это из-за коммита который идет после каждого инсерта, подскажите как лучше делать коммит и запись в базу, и есть ли удобнее метод парсинга чем тот который использую?

main.py
import xml.etree.ElementTree as ET
import condb

tree = ET.parse(filexml)
element_xml_root = tree.getroot()
for elem in element_xml_root.findall('ZAP'):
    idpac = elem.find('ID_PAC').text
    fam = elem.find('FAM').text
    im = elem.find('IM') .text
    ot = elem.find('OT') .text
    Insert_pac(idpac, fam, im, ot)
    for data in elem.findall('DATA'):
        code_usl = data.find('CODE') .text
        date_usl = data.find('DATE') .text
        price_usl = data.find('PRICE') .text
        insert_usl(idpac, code_usl, date_usl, price_usl)


condb.py
import cx_Oracle

def con()
    db = cx_Oracle.connect("SYSTEM", "1234567890", "localhost/ORCL")
    dbcur = db.cursor()


def insert_pac(idpac, fam, im, ot):
        db = con()
        query = dbcur.prepare('INSERT INTO pac_table (idpac, fam, im, ot) VALUES (:idpac, : fam, : im, : ot)')
        dbcur.execute(query, (idpac, fam, im, ot))
        db.commit()
        dbcur.close()

def insert_usl(idpac, code_usl, date_usl, price_usl):
        db = con()
        query = dbcur.prepare('INSERT INTO usl_table (idpac, code_usl, date_usl, price_usl) VALUES (:idpac, : code_usl, : date_usl, : price_usl)')
        dbcur.execute(query, (idpac, code_usl, date_usl, price_usl))
        db.commit()
        dbcur.close()
  • Вопрос задан
  • 262 просмотра
Решения вопроса 1
longclaps
@longclaps
Тормоза в первую очередь из-за постоянного создания-удаления соединения, во-вторую - из-за создания-удаления курсора, в третью - из-за постоянного создания query, в четвёртую - из-за коммитов.
Все эти операции достаточно совершить один раз.

update Владимир, на самом деле я не предлогал создавать 100500 тивиальных функций, можно без них:
import cx_Oracle
import xml.etree.ElementTree as ET

tree = ET.parse(filexml)
element_xml_root = tree.getroot()
db = cx_Oracle.connect("SYSTEM", "1234567890", "localhost/ORCL")
dbcur = db.cursor()
query_pac = dbcur.prepare('INSERT INTO pac_table (idpac, fam, im, ot)'
                          ' VALUES (:idpac, : fam, : im, : ot)')
query_usl = dbcur.prepare('INSERT INTO usl_table (idpac, code_usl, date_usl, price_usl)'
                          ' VALUES (:idpac, : code_usl, : date_usl, : price_usl)')

for elem in element_xml_root.findall('ZAP'):
    idpac = elem.find('ID_PAC').text
    fam = elem.find('FAM').text
    im = elem.find('IM') .text
    ot = elem.find('OT') .text
    dbcur.execute(query_pac, (idpac, fam, im, ot))
    for data in elem.findall('DATA'):
        code_usl = data.find('CODE') .text
        date_usl = data.find('DATE') .text
        price_usl = data.find('PRICE') .text
        dbcur.execute(query_usl, (idpac, code_usl, date_usl, price_usl))
db.commit()
dbcur.close()

зы аккуратно - код написан на коленке ) Я не работал с Oracle и, например, не уверен, нужен ли тут коммит - возможно по умолчанию действует автокоммит при вставке одиночной строки.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
уважаемый longclaps хотел сказать что нужно сделать отдельную функцию под открытие соединения и создание курсора, вторую функцию под инсерты или использовать bulkinsert, третью под коммит, четвертую под закрытие курсора. или же посмотрите есть ли на тригеры на вставку на таблице или же запуск хранимых процедур. это тоже может тормозить процесс.
в вашей ситуации, то что Вы написали, это как прийти в магазин за каждой монетой лезть в кошелек, открывать его, доставать монету, закрывать кошелек, ложить его в карман и потом опять по новой, пока не наберете нужную сумму
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы