-1

Ich habe zwei Tabellen: 1. Benutzertabelle mit rund 10 Millionen Daten Spalten: token_type, cust_id (Primary) 2. pm_tmp Tabelle mit 200k Daten Spalten: id (Primary | AutoIncrement), user_idMysql Performance: Welche der Abfrage dauert mehr Zeit?

User_id ist Fremdschlüssel für cust_id

1. Anfahrt/Abfrage:

update user set token_type='PRIME' 
where cust_id in (select user_id from pm_tmp where id between 1 AND 60000); 

2. Anfahrt/Abfrage: Hier für 60.000 Datensätze für unterschiedliche cust_id einzeln unter Abfrage ausgeführt werden wir:

+3

Wenn Sie es gemessen haben, welche Ergebnisse haben Sie bekommen? –

+0

Der zweite Ansatz dauerte weniger Zeit. Aber ich versuche den Grund dafür herauszufinden. –

+0

Das liegt daran, dass die erste Abfrage ausreichend Speicher für Ihren innodb-Pufferpool benötigt, damit sie schnell ausgeführt werden kann. Zweitens werden Einzeltransaktionsanfragen vergleichsweise weniger Zeit benötigen. – Nans

Antwort

0

Theoretisch ist die Zeit für die erste Abfrage geringer, da weniger Commits und damit weniger Indexneubauten erforderlich sind. Aber, ich würde empfehlen, mit der zweiten Option zu gehen, da es kontrollierter ist und weniger zeitgerecht erscheint und man sich darüber Gedanken machen kann, 2 separate Sets parallel auszuführen.

Hinweis: Die erste Abfrage benötigt ausreichend Speicher, der für mysql-Puffer bereitgestellt wird, damit sie schnell ausgeführt werden kann. Da die zweite Abfrage aus unabhängigen Einzeltransaktionsabfragen besteht, benötigen sie vergleichsweise weniger Speicher und erscheinen daher schneller, wenn sie in begrenzten Speicherumgebungen ausgeführt werden.

Nun, Sie können die erste Abfrage auch auf diese Weise neu schreiben.

update user u, pm_tmp p set u.token_type='PRIME' where u.cust_id=p.id and p.in <60000;

0

Einige Versionen von MySQL Probleme in Optimierung haben. Ich würde empfehlen:

update user u join 
     pm_tmp pt 
     on u.cust_id = pt.user_id and pt.id between 1 AND 60000 
    set u.token_type = 'PRIME' ; 

(Anmerkung: Dies setzt voraus, dass cust_id nicht in pm_temp wiederholt Wenn das möglich ist, sollten Sie eine select distinct Unterabfrage..)

Ihre zweite Version der Regel deutlich langsamer sein würde, weil es erfordert, Tausende von Abfragen statt einer auszuführen. Eine Überlegung könnte die update sein. Vielleicht werden die Protokollierung und das Sperren komplizierter, wenn die Anzahl der Aktualisierungen zunimmt. Ich weiß eigentlich nicht genug über MySQL-Interna, um zu wissen, ob dies die Performance erheblich beeinträchtigen würde.

0

IN (SELECT ...) ist schlecht optimiert. (Ich kann keine Einzelheiten angeben, da sowohl UPDATE als auch IN in einigen neueren Versionen von MySQL besser optimiert wurden.) Es genügt zu sagen: "vermeiden Sie IN (SELECT ...)".

Ihr erster Satz sollte "Zeilen" anstelle von "Spalten" sagen.

Zurück zum Rest der Frage. 60K ist zu groß von einem Stück. Ich empfehle nur 1000. Abgesehen davon ist Gordons Antwort wahrscheinlich die beste.

Aber ... Sie haben OFFSET nicht verwendet; Do nicht versucht sein, es zu verwenden; Es wird die Leistung töten, wenn Sie weiter und weiter in den Tisch gehen.

Eine andere Sache. COMMIT nach jedem Stück. Sonst baut man ein riesiges Undo-Log auf; Dies trägt zu den Kosten bei. (Und ist ein Grund, warum 1K möglicherweise schneller als 60K ist.)

Aber warte! Warum aktualisierst du einen riesigen Tisch? Das ist in der Regel ein Zeichen für schlechtes Schema-Design. Bitte erläutern Sie den Datenfluss.

Vielleicht haben Sie berechnet, welche Elemente als 'prime' markiert werden sollen? Nun, Sie könnten diese Liste herum behalten und JOINs in der SELECTs machen, um Prime-Ness beim Lesen zu entdecken. Dies beseitigt vollständig die UPDATE in Frage. Sicher, die JOIN kostet etwas, aber nicht viel.