2016-03-29 11 views
4

Ich habe eine Tabelle in einer Datenbank, die Elemente speichert. Jeder Artikel hat eine eindeutige ID, die der DB beim Einfügen (Auto-Increment) generiert.
Ein Benutzer kann eine bestimmte Aufgabe ausführen, die der Datenbank X-Elemente hinzufügen, jedoch sollte mein Programm (C++ - Serveranwendung, die den MySQL-Connector verwendet) die IDs zurückgeben, die die Datenbank sofort generiert hat. Wenn ich beispielsweise 6 Elemente hinzufüge, muss der Server 6 neue eindeutige IDs an den Client zurückgeben.
Was ist der schnellste/sauberste Weg, um so etwas zu tun? Bisher habe ich gemacht INSERT gefolgt von SELECT für jeden neuen Artikel ODER INSERT gefolgt von last_insert_id, aber wenn es 50 Elemente hinzufügen, dauert es mindestens ein paar Sekunden, die überhaupt nicht gut für Benutzererfahrung ist.Schnellste Möglichkeit, mehrere eingefügte Zeilen auszuwählen

sql_task.query("INSERT INTO `ItemDB` (`ItemName`, `Type`, `Time`) VALUES ('%s', '%d', '%d')", strName.c_str(), uiType, uiTime); 

gibt es die ID:

uint64_t item_id { sql_task.last_id() }; //This calls mysql_insert_id 
+0

bitte fügen Sie bitte einen Code bitte –

+0

In Ordnung, ich habe etwas Code hinzugefügt. Es funktioniert alles gut, aber es ist überhaupt nicht schnell. – Spook

Antwort

-1

Wie Sie ID autoincremental ist, können Sie nur zwei SELECT Abfragen tun - vor und nach INSERT Anfragen:

SELECT AUTO_INCREMENT FROM information_schema.tables WHERE table_name = 'dbTable' AND table_schema = DATABASE(); 
-- 
-- INSERT INTO dbTable... (one or many, does not matter); 
-- 
SELECT LAST_INSERT_ID() AS lastID; 

Dies gibt Ihnen die Siquence zwischen ersten und letzten eingefügten IDs. Dann können Sie leicht berechnen, wie viele sie sind.

+0

Es ist nicht so einfach. Gleichzeitige Sitzung kann auch die Einfüge-ID erhöhen. Und natürlich multi-Master-Cluster von MySQL nicht um 1 erhöht. – rkosegi

+0

Ich stimme mit rkosegi, da ich auch darüber besorgt bin. Wenn ich ein externes Tool habe, das Elemente zu derselben Tabelle hinzufügen kann, und ich zufällig Elemente gleichzeitig hinzufüge, kann der Client einige IDs erhalten, die unterschiedlich sind. – Spook

+0

@rkosegi im Allgemeinen ja, du hast Recht, aber es kommt darauf an. Da InnoDB während der Einfügung eine Sperre ausführt, müssen andere Einfügungen darauf warten, dass die Einfügung die Transaktion beendet (falls vorhanden). Alles hängt von der Implementierung ab. – mitkosoft

1

Ich glaube, Sie müssen Ihr Design ein wenig überdenken. Lassen Sie uns die Analogie eines Kundenauftrags verwenden. Bei einem Kundenauftrag (oder einer Rechnungsnummer) erhält der Benutzer eine Rechnungsnummer (auto_incr) sowie mehrere Positionsnummern (auch auto_inc).

Der Kundenauftrag und alle Werbebuchungen werden zum Einfügen (über die GUI) ausgewählt und die Einfügungen werden ausgeführt. Zuerst wird die Kundenauftragszeile eingefügt und ihre ID in einer Variablen für nachfolgende Aufrufe zum Einfügen der Werbebuchungen gespeichert. Die Werbebuchungen werden dann jedoch ohne sofortige Rückgabe ihrer auto_inc-ID-Werte eingefügt. Die Anwendung erhält am Ende nur die Kundenauftragsnummer zurück. Wie Ihre App diese Kundenauftragsnummer in nachfolgenden Aufrufen verwendet, bleibt Ihnen überlassen. Es muss jedoch nicht unmittelbar sein, um alle X- oder 50-Zeilen gleichzeitig abzurufen, da die Kundenauftragsnummer irgendwo vereist und gespeichert wird. Nennen wir diese Kundenauftragsnummer XYZ.

Wenn Sie tatsächlich die Informationen benötigen, könnte ein Beispiel Aufruf wie folgt aussehen

select lineItemId 
from lineItems 
where salesOrderNumber=XYZ 
order by lineItemId 

Sie müssen sich daran erinnern, dass in einem Mehrbenutzersystem, dass es keine Garantie dafür gibt einen zusammenhängenden Block von Zahlen des Empfangens . Auch sollte es Ihnen egal sein, da sie alle mit der richtigen Kundenauftragsnummer versehen sind.

Auch dies ist nur eine Analogie, die zu Illustrationszwecken verwendet wird.

+0

Diese Analogie war großartig, danke! Eigentlich ist es nicht einmal mein Design, da ich versuche, das Verhalten eines Servers zu reproduzieren, aber dieser Teil war verwirrend. Ein Benutzer kann mehrere Artikel gleichzeitig kaufen, und der Server fügt sie der Datenbank hinzu und gibt dann für jeden gekauften Artikel eine eindeutige ID an den Kunden zurück. Sie machen es sehr schnell, also habe ich mich gefragt, ob ich etwas verpasst habe. – Spook

0

Das ist ein häufiges, aber schwer zu lösendes Problem. Unsicher für mysql, aber PostreSQL verwendet Sequenzen, um automatische IDs zu generieren. Das Einfügen von Frameworks (objektrelationale Mappers) verwendet das, wenn sie erwarten, viele Werte einzufügen: Sie fragen direkt die Sequenz nach einem Bündel von IDs ab und fügen dann neue Zeilen unter Verwendung dieser bereits bekannten IDs ein. Auf diese Weise ist keine zusätzliche Abfrage nach jedem Einfügen erforderlich, um die ID zu erhalten.

Der Nachteil ist, dass die Relation ID - Insertionszeit nicht monoton sein kann, wenn verschiedene Writer ihre Inserts mischen. Es ist kein Problem für die Datenbank, aber ein (schlecht geschriebenes?) Programm könnte es erwarten.

Verwandte Themen