Le "problème" semble avoir été la conversion de type qui se produit du type décimal de MySQL en decimal.Decimal de python que MySQLdb, pymysql et pyodbc effectuent sur les données. En changeant le fichier converters.py (aux toutes dernières lignes) dans MySQLdb pour avoir :
conversions[FIELD_TYPE.DECIMAL] = float
conversions[FIELD_TYPE.NEWDECIMAL] = float
au lieu de decimal.Decimal semble résoudre complètement le problème et maintenant le code suivant :
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)
S'exécute en moins d'une seconde ! Ce qui est drôle, décimal. Décimal n'a jamais semblé être le problème dans le profileur.
Une solution similaire devrait fonctionner dans le package pymysql. pyodbc est plus délicat :tout est écrit en C++, vous devrez donc recompiler l'intégralité du package.
MISE À JOUR
Voici une solution ne nécessitant pas de modifier le code source MySQLdb :Python MySQLdb renvoie datetime.date et décimal La solution alors pour charger des données numériques dans les pandas :
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)
Bat MATLAB par un facteur d'environ 4 en chargeant une table de 200k x 9 !