Les requêtes exécutées à l'aide du package base de données/sql Go sont nettement plus lentes que les requêtes équivalentes exécutées directement sur la base de données . Pour remédier à cette disparité, il est essentiel d'approfondir les mécanismes sous-jacents.
L'objet sql.DB représente un pool de connexions, pas une seule connexion. Lorsque sql.Open est appelé, il initialise le pool mais ne peut établir aucune connexion. Ce n'est que lorsqu'une requête est demandée qu'une nouvelle connexion est créée.
Dans l'extrait de code fourni, la première requête rencontre un problème de performances car elle déclenche la création d'un nouveau connexion à la base de données. La deuxième requête présente également un écart de performances dû au manque de réutilisation des connexions. Chaque requête établit une nouvelle connexion au lieu d'utiliser une connexion inactive existante du pool.
Pour résoudre ce problème, il est crucial de libérer les connexions vers le pool. après chaque requête. Ceci peut être réalisé en conservant la première valeur de retour de db.Query, qui représente les résultats de la requête, et en invoquant .Close() dessus.
Pour commencer avec un connexion disponible dans le pool, appelez Ping sur l'objet sql.DB après initialisation. Cela forcera la création d'une connexion initiale.
Les instructions préparées sont utilisées lorsque les requêtes contiennent des arguments. Le protocole Postgres active les paramètres au lieu de l'insertion directe de valeurs dans la chaîne de requête. Ce paramétrage séparé permet une gestion plus efficace des requêtes.
L'extrait de code suivant illustre comment gérer correctement les connexions et réutiliser les instructions préparées :
package main import ( "database/sql" "fmt" _ "github.com/lib/pq" "time" ) func main() { // Initialize database connection with initial idle connection db, err := sql.Open("postgres", "postgres:///?sslmode=disable") if err != nil { panic(err) } if err := db.Ping(); err != nil { panic(err) } for i := 0; i < 5; i++ { // Prepare query query := "select 1 where true" stmt, err := db.Prepare(query) if err != nil { panic(err) } // Execute and time query firstQueryStart := time.Now() rows, err := stmt.Query() firstQueryEnd := time.Now() if err != nil { panic(err) } // Release connection back to pool rows.Close() fmt.Println(fmt.Sprintf("query #%d took %s", i, firstQueryEnd.Sub(firstQueryStart).String())) } }
Par en mettant en œuvre ces optimisations, l'écart de performances des requêtes peut être considérablement réduit, offrant des temps d'exécution comparables aux requêtes directes.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!