2013-08-02 2 views
4

Мне нужно прочитать и объединить множество строк (~ 500k) из базы данных PostgreSQL и записать их в базу данных MySQL.Улучшение производительности запросов

Мой наивный подход выглядит следующим образом

entrys = Entry.query.yield_per(500) 

    for entry in entrys: 
     for location in entry.locations: 
      mysql_location = MySQLLocation(entry.url) 
      mysql_location.id = location.id 
      mysql_location.entry_id = entry.id 

      [...] 

      mysql_location.city = location.city.name 
      mysql_location.county = location.county.name 
      mysql_location.state = location.state.name 
      mysql_location.country = location.country.name 

      db.session.add(mysql_location) 

    db.session.commit() 

Каждый Entry имеет около 1 до 100 Locations.

Этот скрипт работает около 20 часов и уже потребляет> 4 ГБ памяти, так как все хранится в памяти до тех пор, пока сеанс не будет зафиксирован.

С моей попыткой совершить ранее, у меня возникают проблемы, такие как this.

Как повысить производительность запроса? Это нужно сделать намного быстрее, так как количество строк в ближайшие месяцы вырастет примерно до 2500 тыс.

+0

Любая причина, по которой вы не можете использовать метод [Извлечь, преобразовать, загрузить] (http://en.wikipedia.org/wiki/Extract,_transform,_load)? – AndrewS

+1

В основном 'pg_dump dbname | mysql dbname' –

+0

@JochenRitzel, я соединяю несколько строк из нескольких таблиц в одну строку для MySQL. Я не вижу, как помочь pg_dump. – dbanck

ответ

1

Ваш наивный подход ошибочен по той причине, что вы уже знаете - вещи, которые едят вашу память, являются объектами модели, болтающимися в памяти, ожидающими, чтобы их покраснели в mysql.

Самый простой способ - не использовать ORM для операций преобразования вообще. Используйте объекты таблицы SQLAlchemy напрямую, так как они также намного быстрее.

Кроме того, что вы можете сделать, это создать 2 сеанса и связать 2 двигателя на отдельные сеансы! Затем вы можете выполнить сеанс mysql для каждой партии.

+0

Я поддерживаю этот вариант двумя отдельными сеансами, где каждый из них будет очищать их с помощью [expunge_all()] (http://docs.sqlalchemy.org/en/rel_0_8/orm/session.html#sqlalchemy.orm. session.Session.expunge_all). Кроме того, на проблемы, с которыми вы работаете (@dbanck), также отвечают, используя запрос диапазона, а не yield_per. – van

Смежные вопросы