Was ist der effizienteste Weg, um eine MySQL-Ergebnismenge in ein NumPy-Array umzuwandeln?

Ich verwende MySQLdb und Python. Ich habe einige grundlegende Fragen wie diese:

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

Ich brauche "Ergebnisse", um ein NumPy-Array zu sein, und ich schaue, um mit meinem Gedächtnisverbrauch ökonomisch zu sein. Es scheint, wie das Kopieren der Daten Zeile für Zeile wäre unglaublich ineffizient (doppelte Speicher wäre erforderlich). Gibt es einen besseren Weg, um MySQLdb-Abfrageergebnisse in das NumPy-Arrayformat umzuwandeln?

Der Grund, warum ich schaue, um das NumPy-Array-Format zu verwenden, ist, weil ich in der Lage sein möchte, die Daten leicht zu schneiden und zu würfeln, und es scheint nicht, wie Python ist sehr freundlich zu mehrdimensionalen Arrays in dieser Hinsicht.

 eg b = a[a[:,2]==1] 

Vielen Dank!

    3 Solutions collect form web for “Was ist der effizienteste Weg, um eine MySQL-Ergebnismenge in ein NumPy-Array umzuwandeln?”

    Die fetchall Methode gibt tatsächlich einen Iterator zurück, und numpy hat die Fromiter- Methode, um ein Array von einem Interator zu initialisieren. Also, je nachdem, welche Daten in der Tabelle sind, können Sie die beiden leicht kombinieren oder einen Adaptergenerator verwenden.

    Diese Lösung nutzt Kieths Fromiter- Technik, behandelt aber die zweidimensionale Tabellenstruktur von SQL-Ergebnissen intuitiver. Außerdem verbessert es die Methode von Doug, indem sie alle Umform- und Abflachungen in Python-Datentypen vermeidet. Mit einem strukturierten Array können wir so ziemlich direkt aus dem MySQL-Ergebnis in numpy lesen und Python-Datentypen fast vollständig ausschneiden. Ich sage 'fast', weil der Fetchall- Iterator noch Python-Tupel produziert.

    Es ist doch eine Einschränkung, aber es ist kein Biggie. Sie müssen den Datentyp Ihrer Spalten und die Anzahl der Zeilen im Voraus kennen.

    Zu wissen, dass die Spaltentypen offensichtlich sein sollten, da Sie wissen, was die Abfrage vermutlich ist, sonst können Sie immer curs.description und eine Karte der MySQLdb.FIELD_TYPE. * Konstanten verwenden.

    Wenn man die Zeilenzählung kennt, muss man den Client-Seitencursor verwenden (was der Standard ist). Ich weiß nicht genug über die Interna von MySQLdb und die MySQL-Client-Bibliotheken, aber mein Verständnis ist, dass das gesamte Ergebnis in Client-Side-Speicher bei der Verwendung von Client-Side-Cursors geholt wird, obwohl ich vermute, es gibt tatsächlich einige Pufferung und Caching beteiligt. Dies würde bedeuten, mit doppeltem Speicher für das Ergebnis, einmal für die Cursor-Kopie und einmal für die Array-Kopie, so ist es wahrscheinlich eine gute Idee, den Cursor so schnell wie möglich zu schließen, um den Speicher freizugeben, wenn die Ergebnismenge groß ist.

    Streng genommen müssen Sie nicht die Anzahl der Zeilen im Voraus zur Verfügung stellen, aber das bedeutet, dass der Array-Speicher einmal im Voraus zugewiesen wird und nicht kontinuierlich verkleinert wird, da mehr Zeilen aus dem Iterator kommen, der dazu bestimmt ist, eine riesige zu liefern Leistungsschub

    Und damit etwas Code

     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.fecthall() 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 

    Sehen Sie sich die numpy Dokumentation für dtype und den Link oben über strukturierte Arrays für die Festlegung von Spalten Datentypen und Spaltennamen.

    NumPys ' abiter- Methode scheint am besten hier zu sein (wie in Keiths Antwort, die diesem vorausging).

    Mit Hilfe von Fromiter , um eine Ergebnismenge neu zu erstellen, die von einem Aufruf einer MySQLdb-Cursor-Methode zurückgegeben wird, ist ein NumPy-Array einfach, aber es gibt ein paar Details, die vielleicht erwähnenswert sind.

     import numpy as NP import MySQLdb as SQL cxn = SQL.connect('localhost', 'some_user', 'their_password', 'db_name') c = cxn.cursor() c.execute('SELECT id, ratings from video') # fetchall() returns a nested tuple (one tuple for each table row) results = cursor.fetchall() # 'num_rows' needed to reshape the 1D NumPy array returend by 'fromiter' # in other words, to restore original dimensions of the results set num_rows = int(c.rowcount) # recast this nested tuple to a python list and flatten it so it's a proper iterable: x = map(list, list(results)) # change the type x = sum(x, []) # flatten # D is a 1D NumPy array D = NP.fromiter(iterable=x, dtype=float, count=-1) # 'restore' the original dimensions of the result set: D = D.reshape(num_rows, -1) 

    Beachten Sie, dass fromiter ein 1D- NumPY-Array zurückgibt,

    (Das macht natürlich Sinn, denn man kann von abitieren , um nur einen Teil einer einzigen MySQL-Tabellenzeile zurückzugeben, indem man einen Parameter für count übergibt).

    Dennoch musst du die 2D-Form wiederherstellen, also der Prädikataufruf zur Cursor-Methode rowcount . Und der anschließende Aufruf zur Umgestaltung in der letzten Zeile.

    Schließlich ist das Standardargument für die Parameterzählung '-1', das nur das gesamte Iterable abruft

    Python ist die beste Programmiersprache der Welt.