Уведомления

Группа в Telegram: @pythonsu

#1 Май 21, 2018 14:36:38

Deesy
Зарегистрирован: 2018-05-21
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Python 3 + параллелизация работы с базой данных

День добрый, господа хорошие.
Ломаю голову. подскажите куда копать.
Суть вопроса: есть python 3.3.6, есть небольшой скрипт. суть скрипта - тянет выборку (датасет1 - только чтение) с MSSQL базы (скажем 20 млн строк). для каждой строки производит сравнение по непростым условиям и в итоге может создать на каждую запись первой выборки - по 2-5 записей (датасет2 - запись), суммирует полученные и сохраняет запись в датасет3 (запись) со значением суммы.
в одном потоке на машине с ксеоном потребляет всего 10-20% ЦПУ и работает достаточно долго (за 8-10 часов). Хотелось бы распараллелить. так как в основном винда то multiprocessor вроде получается только.

Подскажите пожалуйста куда копать. для сохранения в базе, делал батчи инсерта по 500-1000 записей. т.е. готов собирать 500-1000 строк, оборачивать в лист и отсылать воркеру. но тогда получается каждый раз на инициализации/убийстве воркеров время тратится. пусть бы у каждого воркера был бы свой курсор и тянул данные по 500-1000 строк с главного процесса.

помогите пожалуйста советом как организовать.

Офлайн

#2 Май 21, 2018 20:26:06

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

Python 3 + параллелизация работы с базой данных

Deesy
так как в основном винда то multiprocessor
Никак с виндой не связано.
Deesy
всего 10-20% ЦПУ
Это при скольких доступных ядрах?



Офлайн

#3 Май 22, 2018 12:41:17

Deesy
Зарегистрирован: 2018-05-21
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Python 3 + параллелизация работы с базой данных

doza_and
Никак с виндой не связано.
читал что в cpython multithreading работает по-другому из-за реализации GIL. но увы доступны только машины под виндой и только стандартный cpython. сейчас установлен 3.3.4 (пардон, не 3.3.6) но подал заявку на установку последнего 3.6.5 ибо читал что с (насколько я помню) 3.4.Х добавили асинкио. возможно будет полезным для скидывания данных в базу.

doza_and
Это при скольких доступных ядрах?
пардон не дописал. на моей рабочей машине стоит зион с 6-ю ядрами (дополнительно х2 хайпертрединг итого 12) но при работе используется только 1 ядро на 10-20%. но в целом планировалось потом скрипт запускать на отдельной машине.

Отредактировано Deesy (Май 22, 2018 12:47:10)

Офлайн

#4 Май 23, 2018 00:25:06

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

Python 3 + параллелизация работы с базой данных

1 ядро на 10% ??? Ну тут распаралелливание не поможет вы ведь не по прозводительности CPU ограничены. Надо sql запрос оптимизировать и посмотреть как диск загружен.

А оптимизацию надо начинать с профилирования.
https://docs.python.org/3/library/debug.html



Офлайн

#5 Май 23, 2018 01:10:55

Deesy
Зарегистрирован: 2018-05-21
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Python 3 + параллелизация работы с базой данных

примерную хрень проводил отключив выемку данных с датасета1 и заменив на идентичные значения для списка.
увы по сиквелю я больше соображаю чем по питону. выборка с оптимизирована на максимум.

фетчу из датасета по 1 записи. ибо fetchall кмк не втянет 20 млн в память. может быть есть возможность фетчить буфером по 10к?

за линк спасибо, гляну.

Офлайн

#6 Май 23, 2018 22:33:41

doza_and
От:
Зарегистрирован: 2010-08-15
Сообщения: 4138
Репутация: +  252  -
Профиль   Отправить e-mail  

Python 3 + параллелизация работы с базой данных

Deesy
фетчу из датасета по 1 записи.
Что? не так точно не пойдет. Вы должны получить итератор, он не приводит к загрузке всего в память.

Попробуйте привести здесь код который вы используете (упрощенный варимант).



Офлайн

#7 Май 23, 2018 22:41:43

Deesy
Зарегистрирован: 2018-05-21
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Python 3 + параллелизация работы с базой данных

в обычный день может быть 20млн записей. в необычный в 3-4 раза больше.

 def load_and_process_date(day):
    global process_start
    batch_total_started = time.perf_counter()
    batch_total = 0
    batch_current = 0
    row_list = []
    batch_id = 0
    with get_db_connection() as con:
        with get_db_cursor(con) as cur:
            sql = settings.sql_query['LOAD_ICF_DATA']
            sql = sql % day
            cur.execute(sql)
            process_start = time.perf_counter()
            column_names = [col[0] for col in cur.description]
            batch_current_started = time.perf_counter()
            while True:
                row = cur.fetchone()
                if not row:
                    break
                batch_total += 1
                add_txn_data_row(row, day)
                # new_row = dict(zip(column_names, row))
                # add_txn_data_row(new_row, day)
                if batch_current < settings.database['RowsInList']:
                    batch_current += 1
                if batch_current == settings.database['RowsInList']:
                    commit_inserts(day)
                    batch_id += 1
                    print("Avg/1M: {}, {}r/{:.4f} sec. TT: {:.4f} sec.".format(int(
                        (time.perf_counter() - batch_total_started) * 1000000 / 60 / batch_total), batch_total,
                        time.perf_counter() - batch_current_started, time.perf_counter() - batch_total_started))
                    batch_current = 0
                    batch_current_started = time.perf_counter()
    commit_inserts(day)
    return

Отредактировано Deesy (Май 23, 2018 22:42:46)

Офлайн

#8 Май 24, 2018 23:12:44

Kudria
Зарегистрирован: 2016-10-02
Сообщения: 16
Репутация: +  1  -
Профиль   Отправить e-mail  

Python 3 + параллелизация работы с базой данных


Deesy
фетчу из датасета по 1 записи. ибо fetchall кмк не втянет 20 млн в память. может быть есть возможность фетчить буфером по 10к?
Для этого есть fetchmany.

doza_and
Вы должны получить итератор, он не приводит к загрузке всего в память.
Это то-же самое по скорости, что и fetchone использовать.

Офлайн

#9 Май 25, 2018 11:26:57

Rodegast
От: Пятигорск
Зарегистрирован: 2007-12-28
Сообщения: 2750
Репутация: +  184  -
Профиль   Отправить e-mail  

Python 3 + параллелизация работы с базой данных

> тянет выборку (датасет1 - только чтение) с MSSQL базы (скажем 20 млн строк).

Почему пользуйтесь MSSQL? Если есть возможность используй PostgreSQL он даёт возможность делать хранимки на python-е и твой код можно будет запускать прямо на сервере что намного быстрее.

> в одном потоке на машине с ксеоном потребляет всего 10-20% ЦПУ

Ты упираешься в IO, по этому это нормально.

> Хотелось бы распараллелить.

Это делается при помощи модуля threading



С дураками и сектантами не спорю, истину не ищу.
Ели кому-то правда не нравится, то заранее извиняюсь.

Офлайн

#10 Май 25, 2018 11:34:34

Deesy
Зарегистрирован: 2018-05-21
Сообщения: 5
Репутация: +  0  -
Профиль   Отправить e-mail  

Python 3 + параллелизация работы с базой данных

почему MSSQL - потому, что увы не мой выбор (мне оракл больше по-душе). по-тому же почему я не особо могу (надеюсь что пока) поставить python отличный от версии 3.3.4 и т.д. увы тут не мои капризы и сделать-что-то кроме как “вылизать” код на питоне я не могу.

threading юзал, прироста не было. попробую на днях fetchmany() если оно работает с MSSQL отпишусь.

Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version