将 MySQL 结果集转换为 NumPy 数组的最有效方法是什么?

2023-12-24

我正在使用 MySQLdb 和 Python。我有一些基本的疑问,例如:

c=db.cursor()
c.execute("SELECT id, rating from video")
results = c.fetchall()

我需要将“结果”作为 NumPy 数组,并且我希望节省内存消耗。看起来逐行复制数据的效率非常低(需要双倍的内存)。有没有更好的方法将 MySQLdb 查询结果转换为 NumPy 数组格式?

我希望使用 NumPy 数组格式的原因是因为我希望能够轻松地对数据进行切片和切块,而在这方面,Python 对多维数组似乎不太友好。

e.g. b = a[a[:,2]==1] 

Thanks!


该解决方案使用 Kieth'sfromiter技术,但是更直观地处理SQL结果的二维表结构。此外,它还通过避免 python 数据类型中的所有重塑和扁平化来改进 Doug 的方法。用一个结构化数组 http://docs.scipy.org/doc/numpy/user/basics.rec.html我们可以直接从 MySQL 结果读取到 numpy,删除 python 数据类型almost完全。我说“几乎”是因为fetchall迭代器仍然生成 python 元组。

虽然有一个警告,但这不是什么大问题。您必须提前知道列的数据类型和行数。

了解列类型应该是显而易见的,因为您大概知道查询是什么,否则您始终可以使用 curs.description 和 MySQLdb.FIELD_TYPE.* 常量的映射。

知道行数意味着您必须使用客户端游标(这是默认设置)。我对 MySQLdb 和 MySQL 客户端库的内部了解不够,但我的理解是,当使用客户端游标时,整个结果都会被提取到客户端内存中,尽管我怀疑实际上涉及一些缓冲和缓存。这意味着对结果使用双倍内存,一次用于游标复制,一次用于数组复制,因此如果结果集很大,最好尽快关闭游标以释放内存。

严格来说,您不必提前提供行数,但这样做意味着数组内存会提前分配一次,并且不会随着来自迭代器的更多行的出现而连续调整大小,这意味着提供巨大的内存。性能提升。

这样,一些代码

import MySQLdb
import numpy

conn = MySQLdb.connect(host='localhost', user='bob', passwd='mypasswd', db='bigdb')
curs = conn.cursor() #Use a client side cursor so you can access curs.rowcount
numrows = curs.execute("SELECT id, rating FROM video")

#curs.fetchall() is the iterator as per Kieth's answer
#count=numrows means advance allocation
#dtype='i4,i4' means two columns, both 4 byte (32 bit) integers
A = numpy.fromiter(curs.fetchall(), count=numrows, dtype=('i4,i4'))

print A #output entire array
ids = A['f0'] #ids = an array of the first column
              #(strictly speaking it's a field not column)
ratings = A['f1'] #ratings is an array of the second colum

请参阅 dtype 的 numpy 文档和上面有关结构化数组的链接,了解如何指定列数据类型和列名称。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 MySQL 结果集转换为 NumPy 数组的最有效方法是什么? 的相关文章

随机推荐