问题
是否有一种非内存密集型方法可以从 MariaDB 数据库中提取大型数据集并将其直接导入到 Python 中(通过 python-mariadb 连接器)?
背景
我在 Linux 上的 MariaDB 中有一个大型数据库。我经常需要将其中的一部分导入 Python 中以进行进一步的计算。 MariaDB 在内存使用方面相当经济,但 Python 则不然。尽管在 Python 中保存数据的内存密集型方法较少(例如,作为 Pandas DataFrame 为所有列提供适当的数据类型),但通常的工作流程涉及多次复制数据,并且在某些阶段内存需求非常巨大。
简单示例
import pandas as pd
import mariadb
import gc
connection = mariadb.connect(user='<username>', host='localhost', database='my_database')
cursor = connection.cursor(dictionary=False)
query = 'SELECT column_1,column_2 FROM my_table'
cursor.execute(query)
rows = cursor.fetchall()
del cursor
gc.collect()
df = pd.DataFrame(rows)
del rows
gc.collect()
该示例提取了 5 亿行和两列,所有值都是整数。
cursor.execute(statement)
之后,内存使用量约为35GB。 rows = cursor.fetchall()
之后,上升到90GB左右。将数据转换为 pandas DataFrame 并删除其他对象后,内存需求降至约 8GB。我使用 top 监控内存使用情况。
我不确定数据如何保存在光标对象中。我
rows
,它是一个元组列表。 (如果您执行 cursor = connection.cursor(dictionary=True)
来保留列名称,它会变成一个字典列表,每个字典都将列名称作为字符串。不用说,在这种情况下,内存需求将远远超出上面报告的 90GB。)
解决方案的想法
cursor.execute()
之后和在cursor.fetchall()
之后)并直接保存到pandas DataFrame中。 Python-mariadb 似乎没有提供这个。我觉得这并不容易实现。ProtectHome=true
,这将阻止 MariaDB 写入 /home
等中的任何位置。出于安全原因,这是大多数 Linux 的标准。可以通过绑定安装或允许用户来解决此问题搞乱/home
之外的目录,但这些都没有给我留下特别好的想法。)其他信息
MariaDB 版本为 11.2.2,Python 版本为 3.11.6,python-mariadb 连接器版本为 1.1.8,Linux 为 Arch Linux,内核为 6.7.4。
A 计划:在获取 SQL 时进行更多计算。 Python 是解释性的,因此一个数字占用的内存远多于一个数字的内存。
B 计划:用 Python 制作原型,然后音译为 C++。
DOUBLE
仅占用 8 个字节(例如)。