2015-02-20 4 views
0

Я переезжаю данные из Mysql в Postgres и мой код, как показано ниже -MySql FetchMany Проблемы памяти

import os, re, time, codecs, glob, sqlite3 
from StringIO import StringIO 
import psycopg2, MySQLdb, datetime, decimal 
from datetime import date 
import gc 

tables = (['table1' , 27],) 
conn = psycopg2.connect("dbname='xxx' user='xxx' host='localhost' password='xxx' ") 
curpost = conn.cursor() 
db = MySQLdb.connect(host="127.0.0.1", user="root", passwd="root" , unix_socket='/var/mysql/mysql.sock', port=3306) 
cur = db.cursor() 
cur.execute('use xxx;') 

for t in tables: 
    print t 
    curpost.execute("truncate table " + t[0]) 
    cur.execute("select * from "+ t[0]) 
    a = ','.join('%s' for i in range(t[1])) 
    qry = "insert into " + t[0] + " values (" + a +")" 
    print qry 
    i = 0 
    while True: 
     rows = cur.fetchmany(5000) 
     if not rows: break 
     string = '' 
     for row in rows: 
      string = string + ('|'.join([str(x) for x in row])) + "\n"     
     curpost.copy_from(StringIO(string), t[0], sep="|", null="None") 
     i += curpost.rowcount 
     print i , " loaded" 
     curpost.connection.commit()   
     del string, row, rows 
     gc.collect()   

curpost.close() 
cur.close() 

Для небольших таблиц, код работает нормально. Однако более крупные (3,6 миллиона записей), в тот момент, когда выполняется mysql (cur.execute («select * from» + t [0])), использование памяти на компьютере увеличивается. Это даже несмотря на то, что я использовал fetchmany, и записи должны поступать только в партиях 5000. Я также пробовал 500 записей и их же. Для больших таблиц кажется, что fetchmany не работает, как документировано.

Редактировать - я добавил сборку мусора и заявления del. Тем не менее память продолжает раздуваться, пока все записи не обрабатываются.

Любые идеи?

+0

Его 20 минут в настоящее время, использование оперативной памяти составляет около 4 Гб, даже 5000 записей processe d :-( – myloginid

+0

Что вы подразумеваете под ** не работает, как задокументировано ** Не могли бы вы дать мне ссылку, пожалуйста? – Alex

+0

http://dev.mysql.com/doc/connector-python/en/connector-python-api-mysqlcursor-fetchmany.html – myloginid

ответ

0

Извините, если я ошибаюсь, вы сказали, что вы не хотите, чтобы изменить запрос,

Но только в том случае, если у вас нет выбора, вы можете попробовать:

заменить этот фрагмент:

cur.execute("select * from "+ t[0]) 
a = ','.join('%s' for i in range(t[1])) 
qry = "insert into " + t[0] + " values (" + a +")" 
print qry 
i = 0 
while True: 
     rows = cur.fetchmany(5000) 

к этому один:

a = ','.join('%s' for i in range(t[1])) 
qry = "insert into " + t[0] + " values (" + a +")" 
print qry 
i = 0 
while True: 
    cur.execute("select * from "+ t[0]+" LIMIT "+i+", 5000") 
    rows = cur.fetchall() 
+0

Будет ли MySql поддерживать святость номера строки. Я сделал много оракулов раньше и никогда не полагаюсь на любой заказ, предоставленный db. Еще я передам обманы. – myloginid

+0

, чтобы застраховать себя, вы можете добавить «ORDER BY», но обычно это не нужно, если содержимое вашей таблицы не меняется во время цикла другими пользователями. если вам нужно, вы можете начать транзакцию раньше ... но, глядя на ваш код, я думаю, вы пытаетесь преобразовать некоторые данные, поэтому источник данных довольно статичен. просто попробуйте мой путь – Alex

+0

Только что получил результаты. Лимит работал .. У меня 5000 записей с avg-памятью около 100 МБ. И его достигнуто до 45000 записей с той же памятью – myloginid

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