有没有一种非内存密集型的方法将数据从MariaDB导入Python?

问题描述 投票:0回答:1

问题

是否有一种非内存密集型方法可以从 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 似乎没有提供这个。我觉得这并不容易实现。
  • 分块导入数据。在这种情况下,我担心(1)可能的数据类型不一致,(2)最终将数据帧连接成一个数据帧时的内存要求,(3)在更复杂的 MariaDB 查询(尤其是临时查询)的情况下可能会引入可能的不一致将查询结果分割成块的实现),以及(4)计算时间,如果在最坏的情况下,查询可能必须像有块一样运行很多次。
  • 将查询结果保存到硬盘并读回到pandas中。这基本上意味着解决 python-mariadb 连接器已实现的所有内容,并用手动破解替换它。此外,这可能会导致硬盘写入权限出现问题。 (我在 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。

python sql linux memory mariadb
1个回答
0
投票

A 计划:在获取 SQL 时进行更多计算。 Python 是解释性的,因此一个数字占用的内存远多于一个数字的内存。

B 计划:用 Python 制作原型,然后音译为 C++。

DOUBLE
仅占用 8 个字节(例如)。

© www.soinside.com 2019 - 2024. All rights reserved.