У меня довольно стандартный многопроцессорный скрипт, который обрабатывает 2 миллиона записей в таблице базы данных. Прежде чем я даже закончу работу в work_queue, использование памяти превышает 12 ГБ и сбой. Есть ли лучший способ разработать это?Производительность многопроцессорности Python и psycopg2 с большим набором данных
import math
import psycopg2
from psycopg2.extras import DictCursor
from multiprocessing import Process, Manager
from config import DB
connection = psycopg2.connect(DB)
cursor = connection.cursor(cursor_factory=DictCursor)
def worker(worker_queue, progress):
for row in iter(worker_queue.get, None):
# Do work
progress.put(1)
if __name__ == "__main__":
total, done = 0, 0
cursor.execute("SELECT * from table")
manager = Manager()
worker_queue = manager.Queue()
progress = manager.Queue()
for row in cursor:
worker_queue.put(row)
total += 1
workers = [Process(target=worker, args=(worker_queue, progress)) for i in range(50)]
for each in workers:
each.start()
for i in iter(progress.get, None):
done += 1
remaining = total - done
if remaining == 0:
print 'Done'
elif ((remaining % (10 ** int(math.log10(remaining)))) == 0):
print str(remaining) + ' remaining'
Насколько велики ваши данные? Я имею в виду каждую строку. 12Gb более 2 миллионов - это 6.2Kb за строку, которая, кажется, слишком дорога. Если это не так. Возможно, 'select *' не то, что вы хотите - попробуйте уменьшить только до столбцов, которые вы фактически используете. Если это не сработает, возможно, вам придется выполнять эту работу партиями. Другая проблема - «DictCursor». Это, вероятно, удваивает использование вашей памяти, поскольку она превращает кортежи в словари (она должна хранить имена столбцов в каждом dict). Использовать по умолчанию cursor_factory (работа с кортежами). В случае, если имена столбцов имеют значение, равное значению, вы уменьшите использование памяти x2, возможно, больше. – freakish
Обратите внимание, что, например, логическое значение 'True' использует 28b (по крайней мере, в Python3.3), в то время как строка' my_column' 58, которая в два раза больше. Таким образом, вы эффективно задействуете использование памяти с таким булевым столбцом при использовании dicts. – freakish
Да, вот и все! Каждая строка имеет пару сотен полей, и я использовал 20 из них. Выключил DictCursor и только выбрал поля, которые я использовал. Использование памяти превысило 150 мб. – nathancahill