Das "Problem" scheint die Typkonvertierung gewesen zu sein, die von MySQLs Dezimaltyp zu Pythons decimal.Decimal erfolgt, die MySQLdb, pymysql und pyodbc für die Daten durchführen. Indem Sie die Datei converts.py (in den allerletzten Zeilen) in MySQLdb ändern, um Folgendes zu haben:
conversions[FIELD_TYPE.DECIMAL] = float
conversions[FIELD_TYPE.NEWDECIMAL] = float
statt decimal.Decimal scheint das Problem vollständig zu lösen und nun folgender Code:
import MySQLdb
import numpy
import time
t = time.time()
conn = MySQLdb.connect(host='',...)
curs = conn.cursor()
curs.execute("select x,y from TABLENAME")
data = numpy.array(curs.fetchall(),dtype=float)
print(time.time()-t)
Läuft in weniger als einer Sekunde!Lustigerweise dezimal.Dezimal schien nie das Problem im Profiler zu sein.
Eine ähnliche Lösung sollte im Pymysql-Paket funktionieren. pyodbc ist kniffliger:Es ist alles in C++ geschrieben, daher müssten Sie das gesamte Paket neu kompilieren.
AKTUALISIEREN
Hier ist eine Lösung, die keine Änderung des MySQLdb-Quellcodes erfordert:Python MySQLdb gibt datetime.date und decimal zurück Die Lösung dann, numerische Daten in Pandas zu laden:
import MySQLdb
import pandas.io.sql as psql
from MySQLdb.converters import conversions
from MySQLdb.constants import FIELD_TYPE
conversions[FIELD_TYPE.DECIMAL] = float
conversions[FIELD_TYPE.NEWDECIMAL] = float
conn = MySQLdb.connect(host='',user='',passwd='',db='')
sql = "select * from NUMERICTABLE"
df = psql.read_frame(sql, conn)
Schlagt MATLAB um einen Faktor von ~4 beim Laden von 200k x 9-Tabellen!