"Problemet" verkar ha varit typkonverteringen som sker från MySQL:s decimaltyp till pythons decimal.Decimal som MySQLdb, pymysql och pyodbc gör på data. Genom att ändra filen converters.py (på de allra sista raderna) i MySQLdb så att den har:
conversions[FIELD_TYPE.DECIMAL] = float
conversions[FIELD_TYPE.NEWDECIMAL] = float
istället för decimal.Decimal verkar helt lösa problemet och nu följande kod:
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)
Körs på mindre än en sekund! Vad är roligt, decimal. Decimal verkade aldrig vara problemet i profileraren.
Liknande lösning bör fungera i pymysql-paketet. pyodbc är mer knepigt:allt är skrivet i C++, därför måste du kompilera om hela paketet.
UPPDATERA
Här är en lösning som inte behöver ändra MySQLdb-källkoden:Python MySQLdb returnerar datetime.date och decimal Lösningen då att ladda numerisk data till pandor:
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)
Slår MATLAB med en faktor på ~4 vid laddning av 200k x 9 bord!