Ich möchte einige numerische (Double, d. H. Float64) Daten aus einer MySQL-Tabelle lesen. Die Größe der Daten beträgt ~ 200.000 Zeilen.Schnellste Möglichkeit zum Laden numerischer Daten in Python/Pandas/Numpy Array von MySQL
MATLAB Referenz:
tic;
feature accel off;
conn = database(...);
c=fetch(exec(conn,'select x,y from TABLENAME'));
cell2mat(c.data);
toc
verstrichene Zeit ~ 1 Sekunde.
tut das gleiche in Python, die verschiedene Beispiele in hier (ich habe versucht, sie alle, das heißt mit Pandas read_frame, frame_query und der __processCursor-Funktion): How to convert SQL Query result to PANDAS Data Structure?
Referenz Python-Code:
import pyodbc
import pandas.io.sql as psql
import pandas
connection_info = "DRIVER={MySQL ODBC 3.51 \
Driver};SERVER=;DATABASE=;USER=;PASSWORD=;OPTION=3;"
cnxn = pyodbc.connect(connection_info)
cursor = cnxn.cursor()
sql = "select x,y from TABLENAME"
#cursor.execute(sql)
#dataframe = __processCursor(cursor, dataframe=True)
#df = psql.frame_query(sql, cnxn, coerce_float=False)
df = psql.read_frame(sql, cnxn)
cnxn.close()
dauert ~ 6 Sekunden. Profiler sagt, dass die gesamte Zeit in read_frame verbracht wurde. Ich fragte mich, ob jemand mir ein paar Hinweise geben könnte, wie schnell der Matlab-Code zumindest noch schneller sein könnte. Und wenn das bei Python überhaupt möglich ist.
EDIT:
Der Engpass scheint innerhalb der cursor.execute (in pymysql Bibliothek) oder cursor.fetchall() in Pyodbc Bibliothek. Der langsamste Teil liest die zurückgegebenen MySQL-Daten Element für Element (Zeile für Zeile, Spalte für Spalte) und konvertiert sie in den Datentyp, den sie zuvor von derselben Bibliothek abgeleitet hat.
Bisher habe ich es geschafft, dies zu beschleunigen, um MATLAB zu schließen, indem diese wirklich schmutzige Lösung tun:
import pymysql
import numpy
conn = pymysql.connect(host='', port=, user='', passwd='', db='')
cursor = conn.cursor()
cursor.execute("select x,y from TABLENAME")
rez = cursor.fetchall()
resarray = numpy.array(map(float,rez))
finalres = resarray.reshape((resarray.size/2,2))
Die obige cur.execute DIE pymysql NICHT AUSFÜHREN! Ich habe es geändert, in der Datei "connections.py". Erstens hat die Funktion def _read_rowdata_packet, jetzt statt:
rows.append(self._read_row_from_packet(packet))
mit
self._read_string_from_packet(rows,packet)
Hier _read_string_from_packet ersetzt ist eine vereinfachte Version von _read_row_from_packet mit dem Code:
def _read_string_from_packet(self, rows, packet):
for field in self.fields:
data = packet.read_length_coded_string()
rows.append(data)
Dies ist ein Über schmutzige Lösung, die eine Beschleunigung von 6 Sekunden bis 2,5 Sekunden ermöglicht. Ich habe mich gefragt, ob all das irgendwie vermieden werden könnte, wenn man eine andere Bibliothek benutzt/einige Parameter übergibt?
Die Lösung wäre also, die gesamte MySQL-Antwort in einer Liste von Strings zu lesen und dann die Konvertierung in numerische Datentypen zu ändern, anstatt dieses elementweise zu machen. Gibt es sowas schon in Python?
Antworten auf http://stackoverflow.com/questions/7061824/whats-the-most-efficient-way-to-convert-a-mysql-result-set-to-a-numpy-array vorschlagen 'fetchall mit 'gefolgt von' np.fromiter' (mit einer möglichen Umformung). – hpaulj
Danke hpaulj, ich habe es getestet - gleiche (langsame) Geschwindigkeit wie andere Methoden. Das Problem besteht meines Erachtens darin, die Daten aus dem Netzwerk in einen nativen Python-Datentyp zu importieren. Daher tritt dies sowohl in MySQLdb als auch in pymysql in der cursor.execute() auf, was, wenn ich es richtig verstehe, eine falsche Implementierung ist, da nichts in native Datentypen nach dem Ausführen einer SQL-Anweisung "geholt" werden sollte. –