【问题标题】:read_sql() from MySQL is extremely slowMySQL 的 read_sql() 非常慢
【发布时间】:2021-05-29 14:29:08
【问题描述】:

我将 MySQL 与 pandas 和 sqlalchemy 一起使用。但是,它非常缓慢。在一个有 1100 万行的表上完成一个简单的查询需要超过 11 分钟。哪些操作可以提高这种性能?提到的表没有主键,仅由一列索引。

from sqlalchemy import create_engine
import pandas as pd
sql_engine_access = 'mysql+pymysql://root:[password]@localhost')
sql_engine = create_engine(sql_engine_access, echo=False)
script = 'select * from my_database.my_table'
df = pd.read_sql(script, con=self.sql_engine)

【问题讨论】:

  • 您是从云实例或相对较慢的网络连接中拉下这些行吗?每分钟 100 万行等于每秒 16700 行,这并不算慢(大约是我本地 LAN 连接速度的一半)。
  • 所有记录都是使用 python 的 sqlachemy 执行命令获取的。为此,花费了 12 个多小时(获取大约 1100 万行和 58 列)。服务器安装在运行 python 代码的同一台计算机上。没有局域网或云访问。这台计算机有 32 GB 内存和一个 12 核的 AMD 处理器,使用 MS Windows 10 pro。
  • 我还观察到在这些过程中磁盘被大量使用

标签: python mysql python-3.x pandas sqlalchemy


【解决方案1】:

虽然可能不是性能缓慢的全部原因,但一个促成因素是 PyMySQL (mysql+pymysql://) 在重负载下可能比 mysqlclient (mysql+mysqldb://) 慢得多。在一个非常非正式的测试中(没有多次运行,没有平均,没有服务器重新启动)我看到以下结果使用 df.read_sql_query() 对本地 MySQL 数据库:

rows retrieved mysql+mysqldb (seconds) mysql+pymysql (seconds)
1_000_000 13.6 54.0
2_000_000 25.9 114.1
3_000_000 38.9 171.5
4_000_000 62.8 217.0
5_000_000 78.3 277.4

【讨论】:

  • 感谢 Thompson,感谢您的回答并改进了我的问题。事实上,我改为“mysql+mysqldb//”,我的查询变成了 4 mind 而不是 11。这要好得多,尽管我相信其他操作仍有提高性能的空间。
【解决方案2】:

您可以试用我们的工具connectorx (pip install -U connectorx)。它是在 Rust 中实现的,旨在提高 pandas.read_sql 的性能。 API与pandas基本相同。例如,在您的情况下,代码如下所示:

import connectorx as cx
conn_url = "mysql://root:[password]@localhost:port/my_database"
query = "select * from my_table"
df = cx.read_sql(conn_url, query)

如果您的查询结果中有一个像 ID 一样均匀分布的数字列,您还可以通过像这样利用多个核心来进一步加快处理速度:

df = cx.read_sql(conn_url, query, partition_on="ID", partition_num=4)

这将通过过滤ID 列将整个查询拆分为四个小查询,connectorx 将并行运行它们。您可以查看here 了解更多用法和示例。

以下是使用 4 核将 60M 行 x 16 列从 MySQL 加载到 pandas DataFrame 的基准测试结果:

【讨论】:

    猜你喜欢
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 2014-07-16
    • 2010-10-24
    • 2012-09-20
    • 2015-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多