Эффективный дизайн генератора для вставки SQLite3 executemany () на несколько таблиц - PullRequest
1 голос
/ 07 марта 2019

Я анализирую кучу больших XML-файлов в базе данных sqlite3 на python.Как я могу сказать, (хотя я очень открыт и ищу более производительные варианты), более производительным вариантом является executemany() функция sqlite3 для вставок.

Суть того, что я делаю в данный момент, такова:следует:

document_dir = '/documents'

Document = named_tuple('Document', 'doc_id doc_title doc_mentioned_people ... etc')
People = named_tuple('People', 'doc_id first_name last_name ... ') 

class DocumentXML(object):
    """
    ... there's some stuff here, but you get the idea

    """

    def parse_document(path):
        """
        This object keeps track of the current 'document' type element from a cElementTree.iterparse() elsewhere

        I've simplified things here, but you can get the idea that this is providing a named tuple for a generator
        """
        doc_id = _current_element.findall(xpath = '../id')[0].text
        doc_title = _current_element.findall(xpath = '../title')[0].text

        # parse lists of people here

        doc_mentioned_people = People(first_name, last_name, ..., person_id)
        #etc...
        return Document(doc_id, doc_title, doc_mentioned_people, ..., etc)

def doc_generator():
    documents = parse_document(document_dir)
    for doc in documents:
        yield doc.id, doc.title, ..., doc.date



# Import into Table 1
with cursor(True) as c:
        c.executemany("INSERT INTO Document VALUES (?,?,?,?,?,?,?,?,?,?,?);", doc_generator())



def people_generator():
    documents = parse_document(document_dir)
    for doc in documents:
        people = doc.people
        yield people.firstname, people.lastname ..., people.eyecolor


# Import into Table 2
with cursor(True) as c:
        c.executemany("INSERT INTO Document VALUES (?,?,?,?,?,?,?,?,?,?,?);", people_generator())


# This goes on for several tables...

Как видите, здесь ужасный уровень неэффективности.Каждый xml-файл анализируется снова и снова с тем же числом анализаторов, что и таблицы в базе данных.

Я хотел бы использовать только один синтаксический анализ XML (поскольку я могу получить всесоответствующую информацию в одном названном кортеже), но сохраняйте структуру как генератор, чтобы не увеличивать требования к памяти до невыполнимых уровней.

Есть ли хороший способ сделать это?

Мойпопытки вращаются вокруг использования executemany с оператором типа двойной вставки, например:

c.executemany("
    INSERT INTO Document VALUES (?,?,?,?,?,?,?,?,?,?,?);
    INSERT INTO People VALUES (?,?,?,?,?,?,?); 
    INSERT INTO Companies VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?); 
    INSERT INTO Oils VALUES (?,?,?,?,?,?,?); 
    INSERT INTO Physics VALUES (?,?,?,?,?,?,?,?,?,?,?)",
        complete_data_generator())

Где complete_data_generator() возвращает всю соответствующую структурированную информацию;Однако я знаю, что это, скорее всего, не сработает.

Есть ли лучший способ структурировать это для производительности?

1 Ответ

0 голосов
/ 07 марта 2019

Если бы у вас было мало небольших документов, вы бы загрузили все в память и больше не были бы обеспокоены повторным анализом документов.

Если бы у вас была одна таблица для подачи, подход генератора был бы хорош.

Если ни один из этих двух способов не подходит, я бы попробовал подход среднего уровня:

  • анализировать группу файлов XML и накапливать количество doc элементов
  • если у вас есть разумное количество доступных документов, вы приостанавливаете анализ и начинаете подачу таблиц базы данных, используя executemany для этого количества документов
  • вставив этот мешок документов, вы дополнительно обязуетесь освободить файлы журналирования SQLite и возобновите анализ

Плюсы:

  • файлы только анализируютсякогда
  • нагрузкой на базу данных SQLite можно управлять с помощью промежуточных коммитов
  • , которые вы все еще используете executemany

Минусы:

  • много звонков на executemany, в зависимости от vобъем данных
  • каждая фиксация займет некоторое время
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...