【问题标题】:Pandas to_sql() performance - why is it so slow?Pandas to_sql() 性能 - 为什么这么慢?
【发布时间】:2017-02-11 18:18:11
【问题描述】:

我在使用 Pandas 并将 DataFrame 写入 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 测量值。

Multi-threading 不会让这更快。它保持在 7000 - 8000 行/秒内。

CPU时间:用户2分钟6秒,系统:1.69秒,总计:2分钟8秒挂壁时间:2分钟 18秒

截图:

我还增加了max_allowed_packet 的大小以批量提交,块大小更大。仍然没有更快。

这是DataFrame的形状:

netflow_df2.shape
(1015391, 20)

有谁知道我怎样才能使这更快?

【问题讨论】:

    标签: python performance pandas singlestore


    【解决方案1】:

    万一有人遇到类似情况:

    我删除了 SQlalchemy 并为 Pandas 的 to_sql() 函数使用了(已弃用的)MySQL 风格。加速比超过 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 在 mysql.conf 中的max_allowed_packet = 1000M),我会更快。我应该能够在这里每秒超过 50000 行。

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

    126 秒之前。现在 38.2 秒。

    【讨论】:

    • MemSQL 也有 max_allowed_pa​​cket 设置 - docs.memsql.com/docs/memsqlcnf
    • 我一直在测试这个,但似乎我还需要调整一些其他变量。如果我选择了 60 000 的批量大小,我会返回 SQL 语法错误,并且查询会被剪切。
    • 即使使用 to_sql 也很慢。我已经搬到了duckdb github.com/cwida/duckdb。读取和写入数据帧的速度非常快。虽然它是一个嵌入式数据库。看看它是否满足您的需求。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    • 2021-09-03
    • 2014-09-15
    • 2016-09-28
    • 2020-02-08
    • 2012-07-17
    相关资源
    最近更新 更多