Pandas的to_sql()性能为什么如此缓慢?

8
我在使用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测量结果。 多线程不能使其更快,它仍保持在7000-8000行/秒。

CPU时间:用户2分6秒,系统1.69秒,总计2分8秒。墙上时间:2分18秒。

屏幕截图: memSQL shows the speed 我还增加了max_allowed_packet大小以批量提交,并使用更大的块大小,但仍然没有更快。
以下是DataFrame的形状:
netflow_df2.shape
(1015391, 20)

有人知道我如何让它更快吗?
1个回答

2

如果有人遇到类似的情况:

我删除了SQLalchemy,并使用了Pandas中已弃用的MySQL版本的to_sql()函数。速度提高了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秒。


2
MemSQL还具有max_allowed_packet设置 - http://docs.memsql.com/docs/memsqlcnf。 - Jack Chen
我一直在测试这个,但似乎我还需要调整一些其他变量。如果我选择了60,000的批量大小,我会收到SQL语法错误,并且查询会被截断。 - wishi
1
即使使用to_sql也相当慢。我已经转向duckdb https://github.com/cwida/duckdb。将数据框读写到其中非常快速。它是一个嵌入式数据库。看看它是否符合您的需求。 - Wei Qiu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接