Производительность pandas to_sql () - почему она такая медленная?

У меня проблемы с производительностью с Pandas и записи DataFrames в базу данных SQL. Чтобы работать как можно быстрее, я использую memSQL (это похоже на MySQL в коде, поэтому у меня нет ничего не делать). Я только что протестировал свой экземпляр:

docker run --rm -it --link=memsql:memsql memsql/quickstart simple-benchmark
Creating database simple_benchmark
Warming up workload
Launching 10 workers
Workload will take approximately 30 seconds.
Stopping workload
42985000 rows inserted using 10 threads
1432833.3 rows per second

Это не очень хорошо, это просто мой локальный ноутбук. Я знаю ... Я также использую пользователя root, но это одноразовый контейнер Docker.

Вот код, который записывает мой DataFrame в БД:

    import MySQLdb

    import mysql.connector
    from sqlalchemy import create_engine
    from pandas.util.testing import test_parallel

    engine = create_engine('mysql+mysqlconnector://root@localhost:3306/netflow_test', echo=False)
    # max_allowed_packet = 1000M in mysql.conf
    # no effect

    # @test_parallel(num_threads=8)
    def commit_flows(netflow_df2):
        % time netflow_df2.to_sql(name='netflow_ids', con=engine, if_exists = 'append', index=False, chunksize=500)
    commit_flows(netflow_df2)

Ниже показано %time измерение функции.

Многопоточность не ускоряет работу. Остается в пределах 7000-8000 строк / с.

Время ЦП: пользовательское 2 мин. 6 с, системное: 1,69 с, всего: 2 мин. 8 с. Время на стене: 2 мин. 18 с.

Снимок экрана: memSQL показывает скорость

Я также увеличил размер max_allowed_packet для массового коммита с большим размером блока. Все еще не быстрее.

Вот форма DataFrame:

netflow_df2.shape
(1015391, 20)

Кто-нибудь знает, как я могу сделать это быстрее?


person wishi    schedule 03.10.2016    source источник


Ответы (1)


В случае, если у кого-то возникнет похожая ситуация:

Я удалил SQlalchemy и использовал (устаревший) вариант MySQL для функции to_sql() Pandas. Ускорение более 120%. Не рекомендую использовать это, но у меня это работает на данный момент.

import MySQLdb

import mysql.connector
from sqlalchemy import create_engine
from pandas.util.testing import test_parallel

engine = MySQLdb.connect("127.0.0.1","root","","netflow_test")

# engine = create_engine('mysql+mysqlconnector://root@localhost:3306/netflow_test', echo=False)

# @test_parallel(num_threads=8)
def commit_flows(netflow_df2):
    % time netflow_df2.to_sql(name='netflow_ids', flavor='mysql', con=engine, if_exists = 'append', index=False, chunksize=50000)
commit_flows(netflow_df2)

Если я узнаю, как убедить memSQL принять большой запрос (аналогично MySQL max_allowed_packet = 1000M в mysql.conf), я буду еще быстрее. Здесь я должен обрабатывать более 50000 строк в секунду.

CPU times: user 28.7 s, sys: 797 ms, total: 29.5 s
Wall time: 38.2 s

126 сек до. 38,2 с сейчас.

person wishi    schedule 03.10.2016
comment
MemSQL также имеет параметр max_allowed_packet - docs.memsql.com/docs/memsqlcnf. - person Jack Chen; 04.10.2016
comment
Я тестировал это, но, похоже, мне также нужно адаптировать некоторые другие переменные. Если я выберу размер 60 000, я получу синтаксические ошибки SQL, и запрос будет обрезан. - person wishi; 04.10.2016
comment
Даже использование to_sql довольно медленное. Я перешел на duckdb github.com/cwida/duckdb. Чтение и запись фрейма данных в него невероятно быстро. Однако это встроенная база данных. Проверьте, соответствует ли он вашим потребностям. - person Wei Qiu; 12.11.2020