Распараллеливание чтения из базы данных MySQL через Python - PullRequest
5 голосов
/ 20 ноября 2011

Мне нужно прочитать данные из огромной таблицы (> 1 миллиона строк, 16 столбцов необработанного текста) и выполнить некоторые операции с ней. Чтение строк за строкой кажется очень медленным (python, MySQLdb), и я бы хотел иметь возможность читать несколько строк одновременно (возможно, распараллеливать).

Просто к вашему сведению, мой код выглядит примерно так:

cursor.execute('select * from big_table')
rows = int(cursor.rowcount)
for i in range(rows):
    row = cursor.fetchone()
    .... DO Processing ...

Я пытался запустить несколько экземпляров программы для итерации по разным разделам таблицы (например, 1-й экземпляр будет повторять более 1-й строки по 200 КБ, 2-й экземпляр будет повторять по строкам 200k-400k ...), но проблема является то, что 2-й экземпляр (и 3-й экземпляр и т. д.) берет НАВСЕГДА, чтобы добраться до стадии, где он начинает смотреть на строку 200k и далее. Кажется, что он все еще обрабатывает первые 200 тыс. Строк, а не пропускает их. Код, который я использую (для второго экземпляра), в этом случае выглядит примерно так:

for i in range(rows):
    #Fetch the row but do nothing (need to skip over 1st 200k rows)
    row = cur.fetchone()
    if not i in range(200000,400000):
       continue
    .... DO Processing ...

Как я могу ускорить этот процесс? Есть ли чистый способ сделать более быстрое / параллельное чтение из базы данных MySQL через python?

EDIT 1: я попробовал "LIMIT", основываясь на предложениях ниже. По какой-то причине, хотя я запускаю 2 процесса на своем четырехъядерном сервере, кажется, что одновременно запускается только 1 отдельный процесс (кажется, что центральный процессор разделяет время между этими процессами, в отличие от каждого ядра, выполняющего отдельный процесс). 2 процесса Python используют соответственно 14% и 9% процессоров. Есть мысли, что может быть не так?

Ответы [ 3 ]

2 голосов
/ 20 ноября 2011

Предложение LIMIT может принимать два параметра, где первый - это начальная строка, а второй - количество строк.

SELECT ...
 ...
LIMIT 200000,200000
1 голос
/ 20 ноября 2011

Вы также можете столкнуться с конфликтами ввода-вывода на сервере БД (даже если вы получаете данные порциями, на каком-то уровне диски должны сериализовать операции чтения). Таким образом, вместо параллельного чтения из mysql, одно чтение может работать лучше для вас.

Вместо того, чтобы читать 200К строк за раз, вы можете сбросить все данные за одно нажатие и обработать данные (возможно, параллельно) в памяти, в python.

Потенциально вы можете использовать что-то вроде psycopg.copy_expert(). Или, в качестве альтернативы, создайте дамп mysql в одном файле и используйте csv.reader для его итерации (или разделов, если вы обрабатываете его параллельно).

0 голосов
/ 20 ноября 2011

Вы совершенно правы, что ваша попытка распараллелить второй блок запрашивает первые 200 тыс. Записей до того, как они начнут обрабатываться.Вам нужно использовать ключевое слово LIMIT, чтобы попросить сервер вернуть разные результаты:

select * from big_table LIMIT 0,200000
...
select * from big_table LIMIT 200000,200000
...
select * from big_table LIMIT 400000,200000
...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...