2016-02-01 5 views
13

Also habe ich ein Python-Skript, das ungefähr 350.000 Datenobjekte durchläuft, und abhängig von einigen Tests muss es eine Zeile aktualisieren, die jedes dieser Objekte in einer MySQl-Datenbank darstellt. Ich benutze auch pymysql, da ich die geringsten Probleme damit hatte, vor allem, wenn große Select-Abfragen gesendet werden (Select-Anweisungen mit where column IN (....)-Klausel, die mehr als 100.000 Werte enthalten kann).PyMySQL verschiedene Updates in einer Abfrage?

Da jedes Update für jede Zeile unterschiedlich sein kann, ist jede Update-Anweisung anders. Beispielsweise möchten wir für eine Zeile möglicherweise first_name aktualisieren, aber für eine andere Zeile möchten wir first_name unverändert lassen und wir möchten last_name aktualisieren.

Deshalb möchte ich nicht die cursor.executemany() Methode verwenden, die eine generische update-Anweisung und Sie füttert es die Werte wie ich bereits erwähnt, jedes Update ist anders, so dass eine generische update-Anweisung nicht wirklich arbeite für meinen Fall. Ich möchte auch nicht über 350.000 Update-Anweisungen einzeln über die Leitung senden. Kann ich sowieso alle meine Update-Anweisungen zusammenpacken und sie sofort senden?

Ich habe versucht, sie alle in einer Abfrage und mit der cursor.execute()-Methode, aber es scheint nicht alle Zeilen zu aktualisieren.

+0

Wie viele verschiedene Arten Updates gibt es? d. h. wie viele verschiedene Tabellen aktualisieren Sie mit diesen Dritteln einer Million Werte? und wie viele verschiedene Spalten auf diesen Tabellen? Ist es nur ein paar verschiedene Update-Anweisungen? –

+1

Gibt es andere nützliche Optionen als "eine Abfrage" oder "ein Drittel von Millionen" Abfragen? Wie wäre es, wenn die Daten in eine 'Arbeitstabelle' in der Datenbank geladen würden und diese dann manipulieren würden? Datenbank wie mit Daten in Tabellen zu spielen? –

+0

@RyanVincent alle aktualisieren nur die gleiche Tabelle aber die Tabelle hat 12 Spalten und jede Update-Anweisung kann jede andere Kombination von Spalten auf einmal aktualisieren, von 1 Spalte bis 10 Spalten. –

Antwort

4

SQL # 1: CREATE TABLE t mit Spalten, die Sie möglicherweise ändern müssen. Machen Sie alle von ihnen NULL (im Gegensatz zu NOT NULL).

SQL # 2: Führen Sie eine Massenänderung INSERT (oder LOAD DATA) aller erforderlichen Änderungen durch. Wenn Sie beispielsweise nur first_name ändern, geben Sie id und first_name ein, haben Sie jedoch die anderen Spalten NULL.

SQL # 3-14:

UPDATE real_table 
    JOIN t ON t.id = real_table.id 
    SET real_table.first_name = t.first_name 
    WHERE t.first_name IS NOT NULL; 
# ditto for each other column. 

Alle SQLs außer # 1 wird zeitaufwändig sein. Und da UPDATE ein Undo-Protokoll erstellen muss, könnte es Timeout oder anderweitig problematisch sein. Siehe a discussion of chunking, falls erforderlich.

Verwenden Sie bei Bedarf Funktionen wie COALESCE(), GREATEST(), IFNULL() usw.

Massen UPDATEs in der Regel schlechte Schema-Design bedeuten.

(Wenn Ryan springt mit einer ‚Antwort‘, anstatt nur einen ‚Kommentar‘, soll er wahrscheinlich bekommt die ‚Bounty‘. In)

+0

Hallo Rick, Ich weiß, dass Sie meine andere Frage über den Mysql-Connector beantwortet haben, aber ich bekomme einen ähnlichen Fehler, wenn ich versuche, Data Local Infile mit der Pymysql-Bibliothek zu laden. ich ein gebrochenes Rohr Fehler erhalten unabhängig davon, ob ich den Code aus meiner Maschine oder einer EC2-Maschine laufen, wo die DB ein RDS-DB ist so bezweifle ich, das Netz ist, dass gerade für eine Woche crappy 'e_bytes raise err.OperationalError (2006, "MySQL-Server ist weggegangen (% r)"% (e,)) pymysql.err.OperationalError: (2006, "MySQL-Server ist weggegangen (Broken PipeError (32, 'Gebrochene Pipe'))") ' –

5

Ihre beste Leistung sein, wenn Sie Ihre „Tests“ in kodieren die SQL-Logik selbst, so können Sie alles auf eine Handvoll UPDATE-Anweisungen herunterkochen. Oder zumindest so viele wie möglich machen, so dass weniger Zeilen einzeln aktualisiert werden müssen.

Zum Beispiel:

UPDATE tablename set firstname = [some logic] 
WHERE [logic that identifies which rows need the firstname updated]; 

Sie beschreiben nicht viel über Ihre Tests, so dass es schwierig ist, sicher zu sein. Aber mit ein bisschen Arbeit können Sie in Ihrer WHERE-Klausel ziemlich viel Logik finden.

Eine andere Option wäre, Ihre Logik in eine gespeicherte Prozedur zu bringen. Sie werden immer noch 350.000 Updates machen, aber zumindest sind sie nicht alle "über den Draht".Ich würde das nur als letzten Ausweg gebrauchen; Geschäftslogik sollte möglichst in der Anwendungsebene gespeichert werden, und gespeicherte Prozeduren machen Ihre Anwendung weniger portabel.

Verwandte Themen