Mysql
 sql >> Datenbank >  >> RDS >> Mysql

golang SQL-Treiber-Prepare-Anweisung

Die Unterschiede können subtil, manchmal wichtig und manchmal praktisch nicht vorhanden sein.

Im Allgemeinen wird eine vorbereitete Anweisung 1. mit dem Server vorbereitet (SQL geparst, Ausführungsplan generiert usw.), 2. mit den zusätzlichen Parametern ausgeführt und dann 3. geschlossen. Es ermöglicht die Wiederverwendung derselben SQL mit unterschiedlichen Parametern, die jedes Mal übergeben werden, es kann zum Schutz vor SQL-Injection beitragen, kann einige Leistungsverbesserungen bieten (treiber-/protokollspezifisch, YMMV) und wiederholte Schritte verhindern, wie bei der Generierung von Ausführungsplänen und dem Einlesen von SQL die Vorbereitung Schritt oben.

Für jemanden, der Quellcode schreibt, kann eine vorbereitete Anweisung bequemer sein, als Zeichenfolgen zu verketten und diese an den DB-Server zu senden.

Die DB.Query() -Methode akzeptiert SQL als Zeichenfolge und null oder mehr Argumente (wie auch Exec() , oder QueryRow() ). Eine SQL-Zeichenfolge ohne zusätzliche Argumente fragt genau das ab, was Sie geschrieben haben. Wenn jedoch ein SQL-String mit Platzhaltern und zusätzlichen Argumenten bereitgestellt wird, wird unter der Haube eine vorbereitete Anweisung für Sie ausgeführt.

Die DB.Prepare() -Methode führt explizit eine vorbereitete Anweisung aus, an die Sie dann Argumente übergeben, wie in:stmt.Exec(...args) .

Es gibt ein paar Dinge, über die es sich lohnt nachzudenken, in Bezug auf die Unterschiede zwischen den beiden und warum man das eine oder das andere verwendet.

Sie können DB.Query() verwenden ohne Argumente. Dies kann sehr effizient sein, da es prepare --> execute --> close umgehen kann Sequenz, die die vorbereitete Anweisung unbedingt durchläuft.

Sie können es auch mit zusätzlichen Argumenten und Platzhaltern in der Abfragezeichenfolge verwenden, und es wird eine vorbereitete Anweisung unter der Decke ausführen, wie ich oben erwähnt habe. Das potenzielle Problem dabei ist, dass, wenn Sie eine Reihe von Abfragen stellen, jede zu einer vorbereiteten Aussage unter der Haube führt. Da zusätzliche Schritte erforderlich sind, kann dies ziemlich ineffizient sein, da es jedes Mal neu vorbereitet, ausgeführt und geschlossen wird, wenn Sie diese Abfrage durchführen.

Mit einer explizit vorbereiteten Anweisung können Sie diese Ineffizienz möglicherweise vermeiden, da Sie versuchen, die zuvor vorbereitete SQL mit möglicherweise anderen Argumenten wiederzuverwenden.

Aber das funktioniert nicht immer so, wie Sie vielleicht erwarten ... Aufgrund des zugrunde liegenden Verbindungspools, der von db/sql verwaltet wird, ist Ihre "Datenbankverbindung" ziemlich virtuell. Die DB.Prepare() -Methode bereitet die Anweisung für eine bestimmte Verbindung vor und versucht dann, dieselbe Verbindung wiederherzustellen, wenn es Zeit für die Ausführung ist. Wenn diese Verbindung jedoch nicht verfügbar ist, greift sie einfach auf eine verfügbare Verbindung zurück und bereitet sie erneut vor und führt sie dafür aus. Wenn Sie dieselbe vorbereitete Anweisung immer wieder verwenden, bereiten Sie sie möglicherweise unwissentlich auch immer wieder vor. Dies zeigt sich natürlich vor allem bei starkem Verkehr.

Welche Sie für welche Umstände verwenden, hängt also natürlich von Ihrem spezifischen Anwendungsfall ab, aber ich hoffe, die obigen Details helfen Ihnen ausreichend zu klären, damit Sie in jedem Fall die beste Entscheidung treffen können.

Aktualisieren

Angesichts der Aktualisierung in OP gibt es im Wesentlichen keinen Unterschied, wenn die Abfrage nur einmal ausgeführt werden muss, da Abfragen mit Argumenten als vorbereitete Anweisungen hinter den Kulissen ausgeführt werden.

Verwenden Sie die direkten Methoden, z. DB.Query() und seine Analoga, im Vergleich zur expliziten Verwendung vorbereiteter Anweisungen, da dies zu einem etwas einfacheren Quellcode führt.

Da in diesem Fall vorbereitete Anweisungen aus Sicherheitsgründen verwendet werden, kann es sich lohnen, die Sicherheitsbedenken auf andere Weise zu behandeln und stattdessen Klartextabfragen zu verwenden, da dies die Leistung verbessert. Jegliche Gewinne können jedoch irrelevant sein, es sei denn, es gibt genügend Verkehr (oder der Verkehr wird voraussichtlich in der Zukunft erheblich zunehmen), um eine Verringerung der Last auf dem Server zu erfordern. Auch hier kommt es wieder auf den realen Anwendungsfall an.

Für alle, die an Metriken zum Unterschied zwischen vorbereiteten Anweisungen und direkten Klartextabfragen interessiert sind, gibt es einen guten Artikel hier (das auch einen Großteil des oben Gesagten hervorragend erklärt).